diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
index e4945cfc34..85c016fc25 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
@@ -19,6 +19,7 @@
+
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
index 6f9c16ce88..fe4afd6e50 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
@@ -4,6 +4,7 @@ using Volo.Abp.EventBus;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
+using Volo.Abp.ObjectMapping;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Uow;
@@ -18,7 +19,9 @@ namespace Volo.Abp.Domain
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpThreadingModule),
typeof(AbpTimingModule),
- typeof(AbpUnitOfWorkModule))]
+ typeof(AbpUnitOfWorkModule),
+ typeof(AbpObjectMappingModule)
+ )]
public class AbpDddDomainModule : AbpModule
{
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityCreatedEto.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityCreatedEto.cs
new file mode 100644
index 0000000000..d39b69c857
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityCreatedEto.cs
@@ -0,0 +1,17 @@
+using System;
+using Volo.Abp.EventBus;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ [Serializable]
+ [GenericEventName(Postfix = ".Created")]
+ public class EntityCreatedEto
+ {
+ public TEntityEto Entity { get; set; }
+
+ public EntityCreatedEto(TEntityEto entity)
+ {
+ Entity = entity;
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityDeletedEto.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityDeletedEto.cs
new file mode 100644
index 0000000000..9cf930d7db
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityDeletedEto.cs
@@ -0,0 +1,17 @@
+using System;
+using Volo.Abp.EventBus;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ [Serializable]
+ [GenericEventName(Postfix = ".Deleted")]
+ public class EntityDeletedEto
+ {
+ public TEntityEto Entity { get; set; }
+
+ public EntityDeletedEto(TEntityEto entity)
+ {
+ Entity = entity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs
new file mode 100644
index 0000000000..aa2a6e1c8f
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ [Serializable]
+ public class EntityEto : EtoBase
+ {
+ public string KeysAsString { get; set; }
+
+ public EntityEto()
+ {
+
+ }
+
+ public EntityEto(string keysAsString)
+ {
+ KeysAsString = keysAsString;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
new file mode 100644
index 0000000000..354f72dddc
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.DynamicProxy;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.ObjectMapping;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ public class EntityToEtoMapper : IEntityToEtoMapper, ITransientDependency
+ {
+ protected IObjectMapper ObjectMapper { get; }
+ protected DistributedEventBusOptions Options { get; }
+
+ public EntityToEtoMapper(
+ IOptions options,
+ IObjectMapper objectMapper)
+ {
+ ObjectMapper = objectMapper;
+ Options = options.Value;
+ }
+
+ public object Map(object entityObj)
+ {
+ Check.NotNull(entityObj, nameof(entityObj));
+
+ var entity = entityObj as IEntity;
+ if (entity == null)
+ {
+ throw new ArgumentException($"{nameof(entityObj)} should be an entity and implement the '{typeof(IEntity).AssemblyQualifiedName}' interface!");
+ }
+
+ var entityType = ProxyHelper.UnProxy(entity).GetType();
+ var etoType = Options.EtoMappings.GetOrDefault(entityType);
+ if (etoType == null)
+ {
+ var keys = entity.GetKeys().JoinAsString(",");
+ return new EntityEto(keys);
+ }
+
+ //TODO: Also add KeysAsString property to resulting json for compability with the EntityEto!
+ return ObjectMapper.Map(entityType, etoType, entityObj);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityUpdatedEto.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityUpdatedEto.cs
new file mode 100644
index 0000000000..654dd4243f
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityUpdatedEto.cs
@@ -0,0 +1,17 @@
+using System;
+using Volo.Abp.EventBus;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ [Serializable]
+ [GenericEventName(Postfix = ".Updated")]
+ public class EntityUpdatedEto
+ {
+ public TEntityEto Entity { get; set; }
+
+ public EntityUpdatedEto(TEntityEto entity)
+ {
+ Entity = entity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoBase.cs
new file mode 100644
index 0000000000..f574240dc8
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoBase.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ [Serializable]
+ public abstract class EtoBase
+ {
+ public Dictionary Properties { get; }
+
+ protected EtoBase()
+ {
+ Properties = new Dictionary();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs
new file mode 100644
index 0000000000..e33e6751e8
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ public interface IEntityToEtoMapper
+ {
+ object Map(object entityObj);
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/Temp.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/Temp.cs
new file mode 100644
index 0000000000..0ac5b40a47
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/Temp.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.EventBus;
+using Volo.Abp.EventBus.Distributed;
+
+namespace Volo.Abp.Domain.Entities.Events.Distributed
+{
+ /*
+ [EventName("Volo.Abp.Identity.Users.IdentityUser")]
+ public class UserEto : EtoBase
+ {
+ public Guid Id { get; set; }
+
+ public string UserName { get; set; }
+ }
+
+ //Event name (default): [Volo.Abp.Identity.Users.IdentityUser].Created/Updated/Deleted
+
+ public class MyEventHandler : IDistributedEventHandler>
+ {
+ //Event name: Volo.Abp.Identity.Users.IdentityUser.Created
+ public Task HandleEventAsync(EntityCreatedEventInfo eventData)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ */
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
index c557013a03..6d5c03d4e1 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
@@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus;
+using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Uow;
@@ -16,70 +18,65 @@ namespace Volo.Abp.Domain.Entities.Events
public class EntityChangeEventHelper : IEntityChangeEventHelper, ITransientDependency
{
public ILocalEventBus LocalEventBus { get; set; }
+ public IDistributedEventBus DistributedEventBus { get; set; }
- private readonly IUnitOfWorkManager _unitOfWorkManager;
+ protected IUnitOfWorkManager UnitOfWorkManager { get; }
+ protected IEntityToEtoMapper EntityToEtoMapper { get; }
- public EntityChangeEventHelper(IUnitOfWorkManager unitOfWorkManager)
+ public EntityChangeEventHelper(
+ IUnitOfWorkManager unitOfWorkManager,
+ IEntityToEtoMapper entityToEtoMapper)
{
- _unitOfWorkManager = unitOfWorkManager;
+ UnitOfWorkManager = unitOfWorkManager;
+ EntityToEtoMapper = entityToEtoMapper;
+
LocalEventBus = NullLocalEventBus.Instance;
+ DistributedEventBus = NullDistributedEventBus.Instance;
}
public async Task TriggerEventsAsync(EntityChangeReport changeReport)
{
await TriggerEventsInternalAsync(changeReport);
- if (changeReport.IsEmpty() || _unitOfWorkManager.Current == null)
+ if (changeReport.IsEmpty() || UnitOfWorkManager.Current == null)
{
return;
}
- await _unitOfWorkManager.Current.SaveChangesAsync();
+ await UnitOfWorkManager.Current.SaveChangesAsync();
}
public virtual async Task TriggerEntityCreatingEventAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityCreatingEventData<>), entity, true);
- }
-
- public async Task TriggerEntityCreatedEventAsync(object entity)
- {
- await TriggerEventWithEntity(typeof(EntityCreatedEventData<>), entity, true);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityCreatingEventData<>), entity, true);
}
public virtual async Task TriggerEntityCreatedEventOnUowCompletedAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityCreatedEventData<>), entity, false);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityCreatedEventData<>), entity, false);
+ await TriggerEventWithEntity(DistributedEventBus, typeof(EntityCreatedEto<>), EntityToEtoMapper.Map(entity), false);
}
public virtual async Task TriggerEntityUpdatingEventAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityUpdatingEventData<>), entity, true);
- }
-
- public async Task TriggerEntityUpdatedEventAsync(object entity)
- {
- await TriggerEventWithEntity(typeof(EntityUpdatedEventData<>), entity, true);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityUpdatingEventData<>), entity, true);
}
public virtual async Task TriggerEntityUpdatedEventOnUowCompletedAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityUpdatedEventData<>), entity, false);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityUpdatedEventData<>), entity, false);
+ await TriggerEventWithEntity(DistributedEventBus, typeof(EntityUpdatedEto<>), EntityToEtoMapper.Map(entity), false);
}
public virtual async Task TriggerEntityDeletingEventAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityDeletingEventData<>), entity, true);
- }
-
- public async Task TriggerEntityDeletedEventAsync(object entity)
- {
- await TriggerEventWithEntity(typeof(EntityDeletedEventData<>), entity, true);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityDeletingEventData<>), entity, true);
}
public virtual async Task TriggerEntityDeletedEventOnUowCompletedAsync(object entity)
{
- await TriggerEventWithEntity(typeof(EntityDeletedEventData<>), entity, false);
+ await TriggerEventWithEntity(LocalEventBus, typeof(EntityDeletedEventData<>), entity, false);
+ await TriggerEventWithEntity(DistributedEventBus, typeof(EntityDeletedEto<>), EntityToEtoMapper.Map(entity), false);
}
protected virtual async Task TriggerEventsInternalAsync(EntityChangeReport changeReport)
@@ -120,18 +117,18 @@ namespace Volo.Abp.Domain.Entities.Events
}
}
- protected virtual async Task TriggerEventWithEntity(Type genericEventType, object entity, bool triggerInCurrentUnitOfWork)
+ protected virtual async Task TriggerEventWithEntity(IEventPublisher eventPublisher, Type genericEventType, object entity, bool triggerInCurrentUnitOfWork)
{
var entityType = ProxyHelper.UnProxy(entity).GetType();
var eventType = genericEventType.MakeGenericType(entityType);
- if (triggerInCurrentUnitOfWork || _unitOfWorkManager.Current == null)
+ if (triggerInCurrentUnitOfWork || UnitOfWorkManager.Current == null)
{
- await LocalEventBus.PublishAsync(eventType, Activator.CreateInstance(eventType, entity));
+ await eventPublisher.PublishAsync(eventType, Activator.CreateInstance(eventType, entity));
return;
}
- _unitOfWorkManager.Current.OnCompleted(() => LocalEventBus.PublishAsync(eventType, Activator.CreateInstance(eventType, entity)));
+ UnitOfWorkManager.Current.OnCompleted(() => eventPublisher.PublishAsync(eventType, Activator.CreateInstance(eventType, entity)));
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/IEntityChangeEventHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/IEntityChangeEventHelper.cs
index acfcfb9875..59fa72ba09 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/IEntityChangeEventHelper.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/IEntityChangeEventHelper.cs
@@ -10,15 +10,12 @@ namespace Volo.Abp.Domain.Entities.Events
Task TriggerEventsAsync(EntityChangeReport changeReport);
Task TriggerEntityCreatingEventAsync(object entity);
- Task TriggerEntityCreatedEventAsync(object entity);
Task TriggerEntityCreatedEventOnUowCompletedAsync(object entity);
Task TriggerEntityUpdatingEventAsync(object entity);
- Task TriggerEntityUpdatedEventAsync(object entity);
Task TriggerEntityUpdatedEventOnUowCompletedAsync(object entity);
Task TriggerEntityDeletingEventAsync(object entity);
- Task TriggerEntityDeletedEventAsync(object entity);
Task TriggerEntityDeletedEventOnUowCompletedAsync(object entity);
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
new file mode 100644
index 0000000000..b9bcd3ed8b
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+
+namespace Volo.Abp.EventBus.Distributed
+{
+ public class EtoMappingDictionary : Dictionary
+ {
+ public void Add()
+ {
+ this[typeof(TEntity)] = typeof(TEntityEto);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalEventBusOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalEventBusOptions.cs
index 9e48bfa158..045efe9d02 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalEventBusOptions.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalEventBusOptions.cs
@@ -5,10 +5,12 @@ namespace Volo.Abp.EventBus.Distributed
public class DistributedEventBusOptions
{
public ITypeList Handlers { get; }
+ public EtoMappingDictionary EtoMappings { get; set; }
public DistributedEventBusOptions()
{
Handlers = new TypeList();
+ EtoMappings = new EtoMappingDictionary();
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullLocalEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullLocalEventBus.cs
new file mode 100644
index 0000000000..cc59b9a24b
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullLocalEventBus.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Volo.Abp.EventBus.Distributed
+{
+ public sealed class NullDistributedEventBus : IDistributedEventBus
+ {
+ public static NullDistributedEventBus Instance { get; } = new NullDistributedEventBus();
+
+ private NullDistributedEventBus()
+ {
+
+ }
+
+ public IDisposable Subscribe(Func action) where TEvent : class
+ {
+ return NullDisposable.Instance;
+ }
+
+ public IDisposable Subscribe(IEventHandler handler) where TEvent : class
+ {
+ return NullDisposable.Instance;
+ }
+
+ public IDisposable Subscribe() where TEvent : class where THandler : IEventHandler, new()
+ {
+ return NullDisposable.Instance;
+ }
+
+ public IDisposable Subscribe(Type eventType, IEventHandler handler)
+ {
+ return NullDisposable.Instance;
+ }
+
+ public IDisposable Subscribe(IEventHandlerFactory factory) where TEvent : class
+ {
+ return NullDisposable.Instance;
+ }
+
+ public IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
+ {
+ return NullDisposable.Instance;
+ }
+
+ public void Unsubscribe(Func action) where TEvent : class
+ {
+
+ }
+
+ public void Unsubscribe(IEventHandler handler) where TEvent : class
+ {
+
+ }
+
+ public void Unsubscribe(Type eventType, IEventHandler handler)
+ {
+
+ }
+
+ public void Unsubscribe(IEventHandlerFactory factory) where TEvent : class
+ {
+
+ }
+
+ public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
+ {
+
+ }
+
+ public void UnsubscribeAll() where TEvent : class
+ {
+
+ }
+
+ public void UnsubscribeAll(Type eventType)
+ {
+
+ }
+
+ public Task PublishAsync(TEvent eventData) where TEvent : class
+ {
+ return Task.CompletedTask;
+ }
+
+ public Task PublishAsync(Type eventType, object eventData)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/GenericEventNameAttribute.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/GenericEventNameAttribute.cs
index 638a47af0a..8e44905c42 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/GenericEventNameAttribute.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/GenericEventNameAttribute.cs
@@ -5,7 +5,11 @@ namespace Volo.Abp.EventBus
[AttributeUsage(AttributeTargets.Class)]
public class GenericEventNameAttribute : Attribute, IEventNameProvider
{
- public string GetName(Type eventType)
+ public string Prefix { get; set; }
+
+ public string Postfix { get; set; }
+
+ public virtual string GetName(Type eventType)
{
if (!eventType.IsGenericType)
{
@@ -18,7 +22,19 @@ namespace Volo.Abp.EventBus
throw new AbpException($"Given type has more than one generic argument: {eventType.AssemblyQualifiedName}");
}
- return EventNameAttribute.GetNameOrDefault(genericArguments[0]);
+ var eventName = EventNameAttribute.GetNameOrDefault(genericArguments[0]);
+
+ if (!Prefix.IsNullOrEmpty())
+ {
+ eventName = Prefix + eventName;
+ }
+
+ if (!Postfix.IsNullOrEmpty())
+ {
+ eventName = eventName + Postfix;
+ }
+
+ return eventName;
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/NullLocalEventBus.cs
similarity index 97%
rename from framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs
rename to framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/NullLocalEventBus.cs
index f02365d8fa..494db3edd1 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/NullLocalEventBus.cs
@@ -1,8 +1,7 @@
using System;
using System.Threading.Tasks;
-using Volo.Abp.EventBus.Local;
-namespace Volo.Abp.EventBus
+namespace Volo.Abp.EventBus.Local
{
public sealed class NullLocalEventBus : ILocalEventBus
{
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMapperExtensions.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMapperExtensions.cs
new file mode 100644
index 0000000000..eca130638f
--- /dev/null
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMapperExtensions.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Reflection;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public static class ObjectMapperExtensions
+ {
+ private static readonly MethodInfo MapToNewObjectMethod;
+ private static readonly MethodInfo MapToExistingObjectMethod;
+
+ static ObjectMapperExtensions()
+ {
+ var methods = typeof(IObjectMapper).GetMethods();
+ foreach (var method in methods)
+ {
+ if (method.Name == nameof(IObjectMapper.Map) && method.IsGenericMethodDefinition)
+ {
+ var parameters = method.GetParameters();
+ if (parameters.Length == 1)
+ {
+ MapToNewObjectMethod = method;
+ }
+ else if (parameters.Length == 2)
+ {
+ MapToExistingObjectMethod = method;
+ }
+ }
+ }
+ }
+
+ public static object Map(this IObjectMapper objectMapper, Type sourceType, Type destinationType, object source)
+ {
+ return MapToNewObjectMethod
+ .MakeGenericMethod(sourceType, destinationType)
+ .Invoke(objectMapper, new[] { source });
+ }
+
+ public static object Map(this IObjectMapper objectMapper, Type sourceType, Type destinationType, object source, object destination)
+ {
+ return MapToExistingObjectMethod
+ .MakeGenericMethod(sourceType, destinationType)
+ .Invoke(objectMapper, new[] { source, destination });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/ObjectMapperExtensions_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/ObjectMapperExtensions_Tests.cs
new file mode 100644
index 0000000000..3958041817
--- /dev/null
+++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/ObjectMapperExtensions_Tests.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using System;
+using Volo.Abp.AutoMapper.SampleClasses;
+using Volo.Abp.ObjectMapping;
+using Xunit;
+
+namespace Volo.Abp.AutoMapper
+{
+ public class ObjectMapperExtensions_Tests : AbpIntegratedTest
+ {
+ private readonly IObjectMapper _objectMapper;
+
+ public ObjectMapperExtensions_Tests()
+ {
+ _objectMapper = ServiceProvider.GetRequiredService();
+ }
+
+ [Fact]
+ public void Should_Map_Objects_With_AutoMap_Attributes()
+ {
+ var dto = _objectMapper.Map(typeof(MyEntity), typeof(MyEntityDto), new MyEntity { Number = 42 });
+ dto.As().Number.ShouldBe(42);
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericEventNameAttribute_Tests.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericEventNameAttribute_Tests.cs
index 640801ad58..20a9728e7f 100644
--- a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericEventNameAttribute_Tests.cs
+++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericEventNameAttribute_Tests.cs
@@ -1,4 +1,5 @@
-using Shouldly;
+using System.Linq;
+using Shouldly;
using Xunit;
namespace Volo.Abp.EventBus
@@ -8,16 +9,25 @@ namespace Volo.Abp.EventBus
[Fact]
public void Should_Properly_Get_EventName()
{
- new GenericEventNameAttribute()
- .GetName(typeof(MyGenericType))
- .ShouldBe(typeof(MyInnerType).FullName);
+ var eventType = typeof(MyGenericType);
+
+ var eventNameProvider = eventType
+ .GetCustomAttributes(true)
+ .OfType()
+ .Single();
+
+ eventNameProvider
+ .GetName(eventType)
+ .ShouldBe("MyEvent.GenericTest");
}
+ [EventName("MyEvent")]
public class MyInnerType
{
}
+ [GenericEventName(Postfix = ".GenericTest")]
public class MyGenericType
{
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
index 068509cc19..3600ceaeeb 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
@@ -1,10 +1,12 @@
using System;
using System.Collections.ObjectModel;
+using Volo.Abp.AutoMapper;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TestApp.Domain
{
+ [AutoMapTo(typeof(PersonEto))]
public class Person : FullAuditedAggregateRoot, IMultiTenant
{
public virtual Guid? TenantId { get; set; }
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonEto.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonEto.cs
new file mode 100644
index 0000000000..288911da19
--- /dev/null
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonEto.cs
@@ -0,0 +1,17 @@
+using System;
+using Volo.Abp.Domain.Entities.Events.Distributed;
+
+namespace Volo.Abp.TestApp.Domain
+{
+ //[Serializable] //TODO: ???
+ public class PersonEto : EntityEto
+ {
+ public virtual Guid? TenantId { get; set; }
+
+ public virtual Guid? CityId { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual int Age { get; set; }
+ }
+}
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs
index 4de2e405e1..747218984f 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs
@@ -4,6 +4,7 @@ using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.AutoMapper;
+using Volo.Abp.EventBus.Distributed;
using Volo.Abp.TestApp.Application.Dto;
namespace Volo.Abp.TestApp
@@ -18,7 +19,8 @@ namespace Volo.Abp.TestApp
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- ConfigureAutoMapper(context.Services);
+ ConfigureAutoMapper();
+ ConfigureDistributedEventBus();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@@ -26,9 +28,9 @@ namespace Volo.Abp.TestApp
SeedTestData(context);
}
- private static void ConfigureAutoMapper(IServiceCollection services)
+ private void ConfigureAutoMapper()
{
- services.Configure(options =>
+ Configure(options =>
{
options.Configurators.Add(ctx =>
{
@@ -38,6 +40,14 @@ namespace Volo.Abp.TestApp
});
}
+ private void ConfigureDistributedEventBus()
+ {
+ Configure(options =>
+ {
+ options.EtoMappings.Add();
+ });
+ }
+
private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs
index 0fd6a72a04..67032507f3 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs
@@ -2,8 +2,9 @@ using System;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Domain.Entities.Events;
+using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Domain.Repositories;
-using Volo.Abp.EventBus;
+using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
@@ -17,11 +18,13 @@ namespace Volo.Abp.TestApp.Testing
{
protected IRepository PersonRepository { get; }
protected ILocalEventBus LocalEventBus { get; }
+ protected IDistributedEventBus DistributedEventBus { get; }
protected EntityChangeEvents_Tests()
{
PersonRepository = GetRequiredService>();
LocalEventBus = GetRequiredService();
+ DistributedEventBus = GetRequiredService();
}
[Fact]
@@ -31,6 +34,8 @@ namespace Volo.Abp.TestApp.Testing
var creatingEventTriggered = false;
var createdEventTriggered = false;
+ var createdEtoTriggered = false;
+ var updatedEtoTriggered = false;
var updatingEventTriggered = false;
var updatedEventTriggered = false;
@@ -70,6 +75,15 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
+ DistributedEventBus.Subscribe>(eto =>
+ {
+ eto.Entity.Name.ShouldBe(personName);
+
+ createdEtoTriggered = true;
+
+ return Task.CompletedTask;
+ });
+
LocalEventBus.Subscribe>(data =>
{
creatingEventTriggered.ShouldBeTrue();
@@ -100,6 +114,16 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
+ DistributedEventBus.Subscribe>(eto =>
+ {
+ eto.Entity.Name.ShouldBe(personName);
+ eto.Entity.Age.ShouldBe(18);
+
+ updatedEtoTriggered = true;
+
+ return Task.CompletedTask;
+ });
+
PersonRepository.Insert(new Person(Guid.NewGuid(), personName, 15));
uow.Complete();
@@ -107,8 +131,10 @@ namespace Volo.Abp.TestApp.Testing
creatingEventTriggered.ShouldBeTrue();
createdEventTriggered.ShouldBeTrue();
+ createdEtoTriggered.ShouldBeTrue();
updatingEventTriggered.ShouldBeTrue();
updatedEventTriggered.ShouldBeTrue();
+ updatedEtoTriggered.ShouldBeTrue();
}
}
}