繁体   English   中英

如何将命令对象投射到其通用接口?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM