2010-07-21 89 views
2

我有一個co/contra-variance的問題。我知道你不能同時擁有輸入和輸出。因此,這裏是一個簡單的例子:帶輸入和輸出的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; 
} 

的方法我用團結來解決specifc實施者的AB(特別是Implementor),但我所知道的是它是一個A<B>。我不知道有什麼辦法可以直接做到這一點,但我不認爲這是可行的,但是有誰知道解決方法來模擬我正在嘗試做的事情。

回答

0

正如你所說,你不能有兩個輸入和輸出,讓我們改變A<T>A<in T>所以Command可以分配objObject屬性:

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對象作爲輸入!


既然你現在,你將永遠只能傳遞一個BImplementorA<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); 
} 
+0

我知道是這種情況。不幸的是,我寫的方法實際上是類型安全的,因爲我知道Unity將返回一個類型爲'A '的對象,但是沒有切換每種可能的類型,我都不知道方法將其轉換爲正確的類型。我希望有人會有一個解決方法的想法。我的最終目標是能夠使用Unity來解析傳遞給Command的任何特定類型的'A'。 – Stephan 2010-07-21 20:12:24

+0

@Stephan:那些骯髒的反射怎麼樣? 'object a = Unity.Resolve(...); a.GetType()。GetMethod(「SetObject」)。調用(a,new object [] {obj});' – dtb 2010-07-21 20:18:16

+0

我害怕那是我將要得到的答案。雖然這會起作用,但如果沒有其他人有任何其他重組的可能性,這將是最後的選擇。 (還是)感謝你的建議。 – Stephan 2010-07-21 20:29:18