2010-10-22 7 views
2

J'ai besoin d'injecter une collection de type IList<IActivity> dans un constructeur. J'utilise Unity 2.0 et je le configure en utilisant XML.Comment injecter un IList générique <> d'objets en utilisant Unity 2 XML config?

J'ai été capable de le faire en injectant simplement un tableau dans Unity 1.2. Je viens de passer à Unity 2.0 et ma configuration a cessé de fonctionner dans ce domaine spécifique. (. J'ai résolu tous les changements insignifiants au schéma)

Mon constructeur ressemble à ceci:

public DoSomethingWorkflow(IList<IActivity> activityCollection) 
{ 
    ... 
} 

Ma config ressemble à ceci:

<alias alias="IListOfIActivity" type="System.Collections.Generic.IList`1[[MyProject.IActivity, MyProject]], mscorlib"/> 

<alias alias="IActivityArray" type="MyProject.IActivity[], MyProject" /> 

<register type="IWorkflow" mapTo="Workflow" name="DoSomethingWorkflow"> 
    <constructor> 
     <param name="activityCollection" type="IListOfIActivity"> 
     <array> 
      <dependency name="DoSomethingActivity1"/> 
      <dependency name="DoSomethingActivity2"/> 
     </array> 
     </param> 
    </constructor>  
</register> 

Si je lance la config comme ci-dessus Je reçois un message d'erreur indiquant "La configuration est définie pour injecter un tableau, mais le type IList`1 n'est pas un type de tableau".

Si je change à la façon dont il l'habitude de travailler (injecter l'alias de type IActivityArray) Je reçois un message d'erreur indiquant "configuration est incorrect, le MyProject.Workflow type ne dispose pas d'un constructeur qui prend des paramètres nommés ActivityCollection ".

Si je supprime complètement l'attribut type de l'élément constructeur, j'obtiens le même message d'erreur que ci-dessus. La seule façon que je peux faire fonctionner ceci est de changer le constructeur pour accepter un tableau IActivity [] à la place.

Donc, est-ce un bug dans Unity, car un tableau est un IList et devrait trouver le constructeur? Ou ai-je oublié quelque chose dans ma config?

+0

Grande , Je viens d'avoir un badge Tumbleweed pour celui-ci! Quelqu'un peut-il aider? – freshr

+0

Avez-vous déjà découvert cela? –

Répondre

1

Ce que je voudrais faire est de créer un type ActivityList qui dérive de IList<IActivity>.

class ActivityList : IList<IActivity> 
{ /* */ } 

Ce genre de choses dans un fichier de configuration:

System.Collections.Generic.IList`1[[MyProject.IActivity, MyProject]], mscorlib 

est difficile à comprendre et à entretenir.

+0

Le format de '1 [[MyProject.IActivity, MyProject]] était très difficile à trouver. Merci de l'avoir posté! Je suis d'accord, cependant, que c'est difficile à maintenir, mais dans certains cas il n'y a pas d'alternative :-( – Pandincus

2

En fait, vous pouvez essayer d'appliquer un alias au lieu d'hériter d'un nouveau type.

using ActivityList=System.Collections.Generic.List<IActivity>; 
//.... after some declarations 
var activityList = new ActivityList(); 

J'ai lu sur le fichier de configuration Unity. Je sais que vous pouvez créer alias, mais je ne suis pas sûr de savoir comment spécifier génériques

BTW Cet article a une explication une options pour utiliser ;-) génériques http://dotnetslackers.com/articles/net/A-First-Look-at-Unity-2-0.aspx J'espère que cette aide

EDIT:

Après avoir pris le temps d'essayer de l'utiliser, voici ma réponse: Liste Supposons que vous vouliez utiliser la résolution de "IList" à "List". D'abord, vous devrez préparer votre fichier de configuration, dans ce cas, il utilise des références signées à IList ainsi que List.


<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> 
    </configSections> 
    <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
    <alias alias="StringListContract" type="System.Collections.Generic.IList`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    <alias alias="ConcreteStringList" type="System.Collections.Generic.List`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    <container> 
     <register type="StringListContract" mapTo="ConcreteStringList"> 
     <lifetime type="ContainerControlledLifetimeManager" /> 
     <constructor /> 
     </register> 
    </container> 
    </unity> 
</configuration> 

Utilisez le conteneur pour résoudre la dépendance ;-)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Practices.Unity; 
using Microsoft.Practices.Unity.Configuration; 
namespace UnityTerminal 
{ 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      var container = new UnityContainer(); 
      container.LoadConfiguration(); 
      { 
       var concreteStringList = container.Resolve<System.Collections.Generic.IList<System.String>>(); 
       concreteStringList.Add("Hello World"); 
      } 
      { 
       var concreteStringList = container.Resolve<System.Collections.Generic.IList<System.String>>(); 
       Console.WriteLine("{0}", concreteStringList[0]); 
      } 
      Console.ReadKey(); 
     } 
    } 
} 

Cela devrait être suffisant, j'espère que cela fonctionne ;-) Meilleures salutations, Herber