I have an issue with co/contra-variance. I understand you can't have both input and output. So here is a simple example:
public interface A<T>
{
T Object {get;set;}
}
public interface B
{
// Some stuff
}
public class BImplementor : B
{ }
public class Implementor : A<BImplementor> {}
Suppose you have these classes and I'm wanting to write a method like this
public void Command(B obj)
{
var a = (A<B>)Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
a.Ob开发者_如何学Goject = obj;
}
I'm using Unity to resolve a A
of the specifc implementor of B
(specifically Implementor
), but all I know about it is that it is an A<B>
. I don't know of a way to do this directly and I don't think it is actually possible, but does anyone know of a workaround to simulate what I'm trying to do.
As you said, you cannot have both input and output, so let's change A<T>
to A<in T>
so Command
can assign obj
to the Object
property:
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) { ... }
}
The Command
method essentially does this:
public void Command(B obj)
{
A<B> a = (A<B>)new Implementor();
a.SetObject(obj);
}
But this cast can never succeed, because A<B>.SetObject
must accept any B
as input, while Implementor.SetObject
accepts only BImplementor
objects as input!
Since you now that you'll only ever pass a BImplementor
to A<B>.SetObject
, you can work around the problem using reflection.
Workaround 1:
public void Command1(B obj)
{
object a = Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
a.GetType().GetMethod("SetObject").Invoke(a, new object[] { obj });
}
Workaround 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);
}
精彩评论