2011-09-06 125 views
9

這個問題是我之前的問題的後續:Autofac: Hiding multiple contravariant implementations behind one compositeAutofac:解決具有輸入和輸出類型參數的變體類型

我試圖找到我們可以用Autofac的協方差和逆變支持來實現的邊界。我注意到Autofac的ContravariantRegistrationSource只支持通用接口和一個用in關鍵字標記的通用參數。這似乎限制了此功能的實用性,我想知道Autofac是否有其他方法來擴展協方差和逆變的支持。

我必須承認,我不是因爲我正在處理的真實應用程序設計而問這個問題。爲了教育的目的,我故意試圖找到Autofac的限制。

所以考慮以下接口:

public interface IConverter<in TIn, out TOut> 
{ 
    TOut Convert(TIn value); 
} 

而下面的實現:

public class ObjectToStringConverter : IConverter<object, string> 
{ 
    string IConverter<object, string>.Convert(object value) 
    { 
     return value.ToString(); 
    } 
} 

而下面registation:

var builder = new ContainerBuilder(); 

builder.RegisterSource(new ContravariantRegistrationSource()); 

builder.RegisterType<ObjectToStringConverter>() 
    .As<IConverter<object, string>>(); 

var container = builder.Build(); 

採用這種設計和配置,我想希望能夠做到這一點:

// This call succeeds because IConverter<object, string> is 
// explicitly registered. 
container.Resolve<IConverter<object, string>>(); 

// This call fails, although IConverter<string, object> is 
// assignable from IConverter<object, string>. 
container.Resolve<IConverter<string, object>>(); 

還是讓我說得更抽象,用給定的定義:

public class A { } 
public class B : A { } 
public class C : B { } 

public class AToCConverter : IConverter<A, C> { ... } 

而下面的註冊:

builder.RegisterType<AToCConverter>() 
    .As<IConverter<C, A>>(); 

我希望下面的調用成功:

container.Resolve<IConverter<C, A>>(); 
container.Resolve<IConverter<B, B>>(); 
container.Resolve<IConverter<A, C>>(); 

我們如何用Autofac做到這一點?

回答

4

我認爲這是一個我們不太可能在Autofac中克服的侷限性,但它是有趣的探索。

我們可以做contravariant'resolve',因爲給定一個泛型類型參數,我們可以找到該參數可賦值的所有基類型/接口類型。也就是說,給定string我們可以實現搜索objectIComparable

走向相反的方向 - 從參數類型到所有它的子類 - 也不是那麼容易。鑑於object我們需要一些方法來尋找其他的東西。

可以使用在容器中註冊的具體部件的知識,例如,掃描所有尋找可能的實現並向後工作的組件,但這對於Autofac來說並不好,因爲我們在很多情況下依賴於「拉」模式來懶散地創建組件。

希望這是思想的食物,有興趣看看你想出什麼。

1

你是正確的觀察到ContravariantRegistrationSource只能識別具有一個通用參數的類型。看着the source(目前大約在第166行),你會在那裏看到這個限制。考慮如何提供註冊來源來提供可能的候選人,我可以理解,取消限制將需要更多的實施複雜性。

我會說這並不能證明你已達到Autofac的限制,只有這個特定的註冊來源的限制。我將把它作爲練習讓讀者加強ContravariantRegistrationSource的實現,我相信Autofac項目非常樂意接受它回到核心。

+0

與1相等的檢查是計數逆變參數的數量;任意數量的其他(非逆變)參數仍然可以被處理。乾杯! –