mirror of https://github.com/abpframework/abp.git
24 changed files with 469 additions and 46 deletions
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Volo.Abp.Domain.Entities.Events.Distributed |
||||
|
{ |
||||
|
public interface IEntityToEtoMapper |
||||
|
{ |
||||
|
object Map(object entityObj); |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
*/ |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,8 +1,7 @@ |
|||||
using System; |
using System; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp.EventBus.Local; |
|
||||
|
|
||||
namespace Volo.Abp.EventBus |
namespace Volo.Abp.EventBus.Local |
||||
{ |
{ |
||||
public sealed class NullLocalEventBus : ILocalEventBus |
public sealed class NullLocalEventBus : ILocalEventBus |
||||
{ |
{ |
||||
@ -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 }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue