我有一个可以实现ICommand但可以实现通用接口IUpdateAggregateCommand<TAggregate>
的命令对象。
public interface IUpdateAggregateCommand<TAggregate> : ICommand where TAggregate : IAggregate
{
TAggregate Entity { get; set; }
}
我正在测试这样:
var isIUpdateAggregateCommand = command.GetType().GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IUpdateAggregateCommand<>));
如果确实实现了界面,我该如何将其转换为特定类型,例如如果它实现了IUpdateAggregateCommand<Person>
,我该如何将命令强制转换为IUpdateAggregateCommand<Person>
?
我需要能够设置实体的值
我在装饰器内部,我不知道我需要将它投射到的聚合的类型。所以我需要弄清楚它是什么类型然后把它投射到那个
答案 0 :(得分:3)
你不能直接转换吗?
IUpdateAggregateCommand<MyAggregate> updateAggregateCommand = command as IUpdateAggregateCommand<MyAggregate>;
if (updateAggregateCommand != null)
{
updateAggregateCommand.Entity = ...
}
MyAggregate是您定义的类型(显然)。
修改强>
我认为不可能扫描已实现的接口并简单地转换为它们。反思可能是这类工作的最佳解决方案。您可以扫描已实现的接口,然后进行动态方法调用以设置实体。然后,您需要知道实体的类型并相应地实例化或设置它。听起来不太安全。
你想要完成什么?你的装饰师是如何实施的?如果这种方法很麻烦,也许有其他解决方案来解决你的问题。
答案 1 :(得分:2)
您能检查一下您的命令变量是否属于该类型?如果在实例化此命令对象时,它继承自它,则返回true。
if(command is IUpdateAggregateCommand<TAggregate>)
然后你就会:
var newCommand = ((IUpdateAggregateCommand<TAggregate>)command);
或
var newCommand = command as IUpdateAggregateCommand<TAggregate>;
如果您的更新不知道要将其转换为什么,您可以继续使用速度慢的反射,或执行快速,可读的If, Else If
检查,并且您将需要使用某些特殊属性/功能,无论如何都是这种类型的独特之处。
如果您正在寻找 公共属性 ,那么您需要创建一个更通用的接口,这些接口都是从它们继承的,此时您不需要If / Else无论如何。
第二次编辑: 你在寻找像下面这样的概念吗?这允许我根据类型从列表中获取项目,并根据其泛型类型返回它。
List<IMockEvent> events = new List<IMockEvent>();
public IMockEvent<K> GetMockEvent<T, K>()
{
return events.First(t => t is T) as IMockEvent<K>;
}
public void Add(IMockEvent evt)
{
events.Add(new MockStatusUpdate());
}
其中类定义为
public class EMockStatusUpdated : StatusUpdated, IMockEvent<string> { }
public interface IMockEvent<T> : IMockEvent { }
public interface IMockEvent { }
答案 2 :(得分:1)
您可以使用反射来执行此操作:
public static class Extensions
{
private static readonly MethodInfo SetAggregateInternalMethod = typeof(Extensions)
.GetMethod("SetAggregateInternal", BindingFlags.Static | BindingFlags.NonPublic);
private static void SetAggregateInternal<TAggregate>(object item, TAggregate value) where TAggregate : IAggregate
{
var aggregateCommand = item as IUpdateAggregateCommand<TAggregate>;
if (aggregateCommand != null)
aggregateCommand.Entity = value;
}
public static void TrySetAggregate(object item, IAggregate value)
{
SetAggregateInternalMethod
.MakeGenericMethod(value.GetType())
.Invoke(null, new[] { item, value });
}
}
您还可以使用缓存并编译Expression来提高性能。
答案 3 :(得分:1)
public interface IAggregate { }
public class Person : IAggregate { }
public interface ICommand { }
public class BaseCommand : ICommand { }
public interface IUpdateAggregateCommand<out T> : ICommand where T : IAggregate
{
T GetEntity();
}
public class UpdateAggregateCommand<T> : IUpdateAggregateCommand<T> where T : IAggregate
{
private T entity;
public void SetEntity(T t) { this.entity = t; }
public T GetEntity() { return this.entity; }
}
class Program
{
static void Main(string[] args)
{
var command = new BaseCommand();
var obj = command as IUpdateAggregateCommand<IAggregate>;
if (obj != null)
Console.WriteLine(obj.GetEntity().GetType());
var command1 = new UpdateAggregateCommand<Person>();
command1.SetEntity(new Person());
var obj1 = command1 as IUpdateAggregateCommand<IAggregate>;
if (obj1 != null)
Console.WriteLine(obj1.GetEntity().GetType());
}
}