我有co / contra-variance的问题。我知道你不能同时拥有输入和输出。所以这是一个简单的例子:
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;
}
我正在使用Unity来解析A
B
的具体实现者Implementor
,但我所知道的只是A<B>
}。我不知道直接这样做的方法,我不认为它实际上是可能的,但有没有人知道一个解决方法来模拟我正在尝试做的事情。
答案 0 :(得分:0)
正如您所说,您不能同时拥有输入和输出,因此我们将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) { ... }
}
Command
方法实际上是这样做的:
public void Command(B obj)
{
A<B> a = (A<B>)new Implementor();
a.SetObject(obj);
}
但此演员表永远不会成功,因为A<B>.SetObject
必须接受任何B
作为输入,而Implementor.SetObject
仅接受BImplementor
个对象作为输入!
由于您现在只能将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);
}