代码之家  ›  专栏  ›  技术社区  ›  Stephan

与输入和输出的协/反方差

  •  2
  • Stephan  · 技术社区  · 14 年前

    我对协变/反变有异议。我知道你不能同时拥有输入和输出。下面是一个简单的例子:

    public interface A<T>
    {
        T Object {get;set;}
    }
    
    public interface B
    {
        // Some stuff
    }
    
    public class BImplementor : B
    { }
    
    public class Implementor : A<BImplementor> {}
    

    假设你有这些类,我想写一个这样的方法

    public void Command(B obj)
    {
        var a = (A<B>)Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
        a.Object = obj;
    }
    

    我用团结来解决 A 特定实施者的 B (具体地说) Implementor 但我所知道的是 A<B> . 我不知道如何直接做到这一点,我认为这实际上是不可能的,但是否有人知道一个变通方法来模拟我正在做的事情。

    1 回复  |  直到 14 年前
        1
  •  0
  •   dtb    14 年前

    正如您所说,您不能同时拥有输入和输出,所以让我们改变一下 A<T> A<in T> 所以 Command 可以分配 obj Object 财产:

    public interface A<in T>
    {
        void SetObject(T obj);
    }
    
    public interface B { }
    
    public class BImplementor : B { }
    
    public class Implementor : A<BImplementor>
    {
        public void SetObject(BImplementor t) { ... }
    }
    

    这个 命令 方法基本上是这样做的:

    public void Command(B obj)
    {
        A<B> a = (A<B>)new Implementor();
        a.SetObject(obj);
    }
    

    但是这个演员永远不会成功,因为 A<B>.SetObject 必须接受任何 B 作为输入,同时 Implementor.SetObject 只接受 BImplementor 对象作为输入!


    既然你现在只会通过 二者 A<B>.setObject对象 ,您可以使用反射来解决问题。

    工作1:

    public void Command1(B obj)
    {
        object a = Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
        a.GetType().GetMethod("SetObject").Invoke(a, new object[] { obj });
    }
    

    工作2:

    public void Command(B obj)
    {
        this.GetType()
            .GetMethod("Command2")
            .MakeGenericMethod(obj.GetType())
            .Invoke(this, new object[] { obj });
    }
    
    public void Command2<T>(T obj) where T : B
    {
        A<T> a = Unity.Resolve<A<T>>();
        a.SetObject(obj);
    }