0

我有一个可以实现 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>

我需要能够设置实体的值

更新

我在一个装饰器里面,我不知道我需要将它转换成的聚合类型。所以我需要弄清楚它是什么类型,然后将其转换为

4

4 回答 4

3

不能直接转换吗?

IUpdateAggregateCommand<MyAggregate> updateAggregateCommand = command as IUpdateAggregateCommand<MyAggregate>;
if (updateAggregateCommand != null)
{
    updateAggregateCommand.Entity = ...
}

MyAggregate 是您定义的类型(显然)。

编辑:

我认为不可能扫描已实现的接口并简单地转换为它们。反射可能是这种工作的最佳解决方案。您可以扫描已实现的接口,然后进行动态方法调用以设置实体。然后你需要知道实体的类型并相应地实例化或设置它。听起来不是很安全。

你想达到什么目的?你的装饰器是如何实现的?如果这种方法很麻烦,也许还有其他解决方案可以解决您的问题。

于 2013-09-20T16:40:50.433 回答
2

您能否检查一下您的命令变量是否属于该类型?如果在实例化此命令对象时,它继承自它,它将返回 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 { }
于 2013-09-20T16:41:11.303 回答
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());
    }
}
于 2013-09-20T18:23:13.573 回答
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来提高性能。

于 2013-09-20T16:54:23.363 回答