Browse Source

Trigger distributed events on entity changes

pull/603/head
Halil ibrahim Kalkan 8 years ago
parent
commit
127f389819
  1. 1
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  2. 5
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
  3. 17
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityCreatedEto.cs
  4. 17
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityDeletedEto.cs
  5. 20
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs
  6. 46
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
  7. 17
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityUpdatedEto.cs
  8. 16
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoBase.cs
  9. 7
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs
  10. 29
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/Temp.cs
  11. 57
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
  12. 3
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/IEntityChangeEventHelper.cs
  13. 13
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
  14. 2
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalEventBusOptions.cs
  15. 90
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/NullLocalEventBus.cs
  16. 20
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/GenericEventNameAttribute.cs
  17. 3
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/NullLocalEventBus.cs
  18. 45
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMapperExtensions.cs
  19. 26
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/ObjectMapperExtensions_Tests.cs
  20. 18
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericEventNameAttribute_Tests.cs
  21. 2
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
  22. 17
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonEto.cs
  23. 16
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs
  24. 28
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs

1
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -19,6 +19,7 @@
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<ProjectReference Include="..\Volo.Abp.Uow\Volo.Abp.Uow.csproj" />

5
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
{

17
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<TEntityEto>
{
public TEntityEto Entity { get; set; }
public EntityCreatedEto(TEntityEto entity)
{
Entity = entity;
}
}
}

17
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<TEntityEto>
{
public TEntityEto Entity { get; set; }
public EntityDeletedEto(TEntityEto entity)
{
Entity = entity;
}
}
}

20
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;
}
}
}

46
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<DistributedEventBusOptions> 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);
}
}
}

17
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<TEntityEto>
{
public TEntityEto Entity { get; set; }
public EntityUpdatedEto(TEntityEto entity)
{
Entity = entity;
}
}
}

16
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<string, object> Properties { get; }
protected EtoBase()
{
Properties = new Dictionary<string, object>();
}
}
}

7
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);
}
}

29
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<EntityCreatedEventInfo<Temp>>
{
//Event name: Volo.Abp.Identity.Users.IdentityUser.Created
public Task HandleEventAsync(EntityCreatedEventInfo<Temp> eventData)
{
throw new NotImplementedException();
}
}
*/
}

57
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)));
}
}
}

3
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);
}
}

13
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<Type, Type>
{
public void Add<TEntity, TEntityEto>()
{
this[typeof(TEntity)] = typeof(TEntityEto);
}
}
}

2
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<IEventHandler> Handlers { get; }
public EtoMappingDictionary EtoMappings { get; set; }
public DistributedEventBusOptions()
{
Handlers = new TypeList<IEventHandler>();
EtoMappings = new EtoMappingDictionary();
}
}
}

90
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<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent, THandler>() where TEvent : class where THandler : IEventHandler, new()
{
return NullDisposable.Instance;
}
public IDisposable Subscribe(Type eventType, IEventHandler handler)
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
return NullDisposable.Instance;
}
public void Unsubscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
}
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
}
public void Unsubscribe(Type eventType, IEventHandler handler)
{
}
public void Unsubscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
}
public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
}
public void UnsubscribeAll<TEvent>() where TEvent : class
{
}
public void UnsubscribeAll(Type eventType)
{
}
public Task PublishAsync<TEvent>(TEvent eventData) where TEvent : class
{
return Task.CompletedTask;
}
public Task PublishAsync(Type eventType, object eventData)
{
return Task.CompletedTask;
}
}
}

20
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;
}
}
}

3
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs → 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
{

45
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 });
}
}
}

26
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<AutoMapperTestModule>
{
private readonly IObjectMapper _objectMapper;
public ObjectMapperExtensions_Tests()
{
_objectMapper = ServiceProvider.GetRequiredService<IObjectMapper>();
}
[Fact]
public void Should_Map_Objects_With_AutoMap_Attributes()
{
var dto = _objectMapper.Map(typeof(MyEntity), typeof(MyEntityDto), new MyEntity { Number = 42 });
dto.As<MyEntityDto>().Number.ShouldBe(42);
}
}
}

18
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<MyInnerType>))
.ShouldBe(typeof(MyInnerType).FullName);
var eventType = typeof(MyGenericType<MyInnerType>);
var eventNameProvider = eventType
.GetCustomAttributes(true)
.OfType<IEventNameProvider>()
.Single();
eventNameProvider
.GetName(eventType)
.ShouldBe("MyEvent.GenericTest");
}
[EventName("MyEvent")]
public class MyInnerType
{
}
[GenericEventName(Postfix = ".GenericTest")]
public class MyGenericType<T>
{

2
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<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; set; }

17
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; }
}
}

16
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<AbpAutoMapperOptions>(options =>
Configure<AbpAutoMapperOptions>(options =>
{
options.Configurators.Add(ctx =>
{
@ -38,6 +40,14 @@ namespace Volo.Abp.TestApp
});
}
private void ConfigureDistributedEventBus()
{
Configure<DistributedEventBusOptions>(options =>
{
options.EtoMappings.Add<Person, PersonEto>();
});
}
private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())

28
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<Person, Guid> PersonRepository { get; }
protected ILocalEventBus LocalEventBus { get; }
protected IDistributedEventBus DistributedEventBus { get; }
protected EntityChangeEvents_Tests()
{
PersonRepository = GetRequiredService<IRepository<Person, Guid>>();
LocalEventBus = GetRequiredService<ILocalEventBus>();
DistributedEventBus = GetRequiredService<IDistributedEventBus>();
}
[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<EntityCreatedEto<PersonEto>>(eto =>
{
eto.Entity.Name.ShouldBe(personName);
createdEtoTriggered = true;
return Task.CompletedTask;
});
LocalEventBus.Subscribe<EntityUpdatingEventData<Person>>(data =>
{
creatingEventTriggered.ShouldBeTrue();
@ -100,6 +114,16 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
DistributedEventBus.Subscribe<EntityUpdatedEto<PersonEto>>(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();
}
}
}

Loading…
Cancel
Save