4

我有一個類需要一個IEnumerable構造函數參數,我想用Unity解析並注入一個對象數組。這些簡單的類說明了這個問題。如何配置Unity爲IEnumerable注入數組

public interface IThing 
{ 
    int Value { get; } 
} 

public class SimpleThing : IThing 
{ 
    public SimpleThing() 
    { 
     this.Value = 1; 
    } 

    public int Value { get; private set; } 
} 

public class CompositeThing : IThing 
{ 
    public CompositeThing(IEnumerable<IThing> otherThings) 
    { 
     this.Value = otherThings.Count(); 
    } 

    public int Value { get; private set; } 
} 

說我要注入4 SimpleThingCompositeThing。我已經嘗試了以下Unity配置的幾種變體。

<alias alias="IThing" type="TestConsoleApplication.IThing, TestConsoleApplication" /> 
<alias alias="SimpleThing" type="TestConsoleApplication.SimpleThing, TestConsoleApplication" /> 
<alias alias="CompositeThing" type="TestConsoleApplication.CompositeThing, TestConsoleApplication" /> 

<container> 

    <register type="IThing" mapTo="SimpleThing" name="SimpleThing" /> 
    <register type="IThing" mapTo="CompositeThing" name="CompositeThing"> 
    <constructor> 
     <param name="otherThings"> 
     <array> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
     </array> 
     </param> 
    </constructor> 
    </register> 

</container> 

但是我得到的結構被設置爲注入陣列錯誤消息,但類型IEnumerable`1不是數組類型。如果我將構造函數參數更改爲IThing[]它可以工作,但我不想這樣做。我需要對Unity配置做些什麼才能使其發揮作用?

+0

可能的重複[解決IEnumerable 與Unity](http://stackoverflow.com/questions/1961549/resolving-ienumerablet-with-unity) – 2011-12-15 11:57:15

+3

我不認爲這是重複的,因爲該問題是關於程序註冊而我使用的配置文件。 – batwad 2011-12-15 12:17:43

回答

3

下面是我找到的一個解決方案,但它有點不起眼。你需要一個包裝類來幫助Unity識別一個數組是IEnumerable

public class ArrayWrapper<T> : IEnumerable<T> 
{ 
    public ArrayWrapper(T[] things) 
    { 
     this.things = things; 
    } 

    private IEnumerable<T> things; 

    IEnumerator<T> IEnumerable<T>.GetEnumerator() 
    { 
     return this.things.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.things.GetEnumerator(); 
    } 
} 

然後,您可以配置Unity使用Ethan的EnumberableThing想法注入其中之一。

<alias alias="IThing" type="TestConsoleApplication.IThing, TestConsoleApplication" /> 
<alias alias="SimpleThing" type="TestConsoleApplication.SimpleThing, TestConsoleApplication" /> 
<alias alias="CompositeThing" type="TestConsoleApplication.CompositeThing, TestConsoleApplication" /> 
<alias alias="EnumerableThing" type="System.Collections.Generic.IEnumerable`1[[TestConsoleApplication.IThing, TestConsoleApplication]], mscorlib"/> 
<alias alias="ThingArrayWrapper" type="TestConsoleApplication.ArrayWrapper`1[[TestConsoleApplication.IThing, TestConsoleApplication]], TestConsoleApplication"/> 

<container> 
    <register type="EnumerableThing" mapTo="ThingArrayWrapper"> 
    <constructor> 
     <param name="things"> 
     <array> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
      <dependency type="SimpleThing"/> 
     </array> 
     </param> 
    </constructor> 
    </register> 

    <register type="IThing" mapTo="SimpleThing" name="SimpleThing" /> 

    <register type="IThing" mapTo="CompositeThing" name="CompositeThing"> 
    <constructor> 
     <param name="otherThings" dependencyType="EnumerableThing" /> 
    </constructor> 
    </register> 
</container> 

就像我說的雖然有點俗套和尷尬,當你想另一個CompositeThing有三,五,六樣東西等

當然應該團結能夠識別那一個數組是IEnumberable並注入它?

0

對於Unity配置,沒有默認支持IEnumerable<T>依賴關係。使用現有統一配置實現您的目標的唯一選擇是將IEnumerable<T>映射到T [],如下所示。

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
<alias alias="IThing" type="TestConsoleApplication.IThing, TestConsoleApplication" /> 
<alias alias="SimpleThing" type="TestConsoleApplication.SimpleThing, TestConsoleApplication" /> 
<alias alias="CompositeThing" type="TestConsoleApplication.CompositeThing, TestConsoleApplication" /> 
<alias alias="EnumerableThing" type="System.Collections.Generic.IEnumerable`1[[TestConsoleApplication.IThing, TestConsoleApplication]], mscorlib"/> 
<alias alias="ThingArray" type="TestConsoleApplication.IThing[], TestConsoleApplication"/> 

<container> 
    <register type="EnumerableThing" mapTo="ThingArray"/> 
    <register type="IThing" mapTo="SimpleThing" name="SimpleThing" /> 
    <register type="IThing" mapTo="CompositeThing"> 
    <constructor> 
     <param name="otherThings" dependencyType="EnumerableThing"/> 
    </constructor> 
    </register> 
</container> 

C#代碼:

IUnityContainer container = new UnityContainer(); 
container.LoadConfiguration(); 
IThing thing = container.Resolve<CompositeThing>(); 
Console.WriteLine(thing.Value); 

如果你不想這樣,我想你可以擴展統一配置系統以支持IEnumerable<T>依賴解決,通過實施新EnumerableElement繼承ParameterValueElement。

1

其實Unity理解數組。接受的解決方案會是不錯的,但如果你不想要的包裝只要你想給所有註冊的實現取它的那麼容易,因爲:

public class CompositeThing : IThing 
{ 
    public CompositeThing(IThing[] otherThings) 
    { 
     this.Value = otherThings.Count(); 
    } 

    public int Value { get; private set; } 
} 

的缺點是,它可能也將會返回一個實例如果它本身是IThing的話。

Similiar的問題在這裏: How to inject IEnumerable using Microsoft Unity IOC container

只要確保有一個特定的名稱註冊的實現,因爲這樣的:

container.RegisterType<IThing, FooThing>("Foo"); 
container.RegisterType<IThing, BarThing>("Bar"); 

我不知道XML語法,但我相信你能有實現它。

相關問題