![](/img/trans.png)
[英]Why can I not cast to a generic interface from a type with a generic argument which is a subtype of the generic argument in my interface?
[英]How can I cast my command object to its generic interface?
我有一个命令对象,它可以实现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>
如何将命令IUpdateAggregateCommand<Person>
为IUpdateAggregateCommand<Person>
?
我需要能够设置Entity的值
我在一个装饰器中,我不知道将其投射到的聚合的类型。 所以我需要弄清楚它是什么类型,然后将其强制转换为
您不能直接转换吗?
IUpdateAggregateCommand<MyAggregate> updateAggregateCommand = command as IUpdateAggregateCommand<MyAggregate>;
if (updateAggregateCommand != null)
{
updateAggregateCommand.Entity = ...
}
MyAggregate是您(显然)定义的类型。
编辑:
我认为不可能扫描已实现的接口并将其简单地转换为它们。 反思可能是此类工作的最佳解决方案。 您可以扫描已实现的接口,然后进行动态方法调用以设置实体。 然后,您再次需要知道实体的类型并实例化或相应地设置它。 听起来不太安全。
你想达到什么目的? 装饰器如何实施? 如果这种方法很麻烦,也许还有其他解决方案可以解决您的问题。
您能否检查一下您的命令变量是否为类型? 如果在实例化此命令对象时继承了该命令对象,则它将返回true。
if(command is IUpdateAggregateCommand<TAggregate>)
然后,您将:
var newCommand = ((IUpdateAggregateCommand<TAggregate>)command);
要么
var newCommand = command as IUpdateAggregateCommand<TAggregate>;
如果您不知道将其投射到哪个更新中,则可以继续使用反射缓慢的反射,或者继续使用If, Else If
检查快速,易读的反射,并且您将需要使用一些特殊的属性/功能无论如何,这种类型是唯一的。 如果您正在寻找一个公共属性 ,那么您需要创建一个它们都继承自的通用接口,这时无论如何您都不需要If / Else If。
第二编辑:您是否正在寻找类似以下的概念? 这使我可以根据列表的类型从列表中获取一个项目,并根据其通用类型将其返回。
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 { }
您可以使用反射来做到这一点:
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来提高性能。
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());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.