Domanda

Sto cercando di capire l'attributo di iniezione del costruttore del MEF. Non ho idea di come lo dico per caricare i parametri del costruttore.

Questa è la proprietà che sto cercando di caricare

[ImportMany(typeof(BUsers))]
public IEnumerable<BUsers> LoadBUsers { get; set; }

Ecco il codice che sto usando per importare le assemblee.

try
{
    var catalog = new AggregateCatalog();
    catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
    catalog.Catalogs.Add(new DirectoryCatalog("DI")); 
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
}

Questa è la classe che sto cercando di caricare

[Serializable]
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
    [ImportingConstructor]
    public EditProfile(string Method, string Version)
    {            
        Version = "2";
        Action = "Edit";
        TypeName = "EditProfile";
    }
È stato utile?

Soluzione

Quando si utilizza l'attributo ImportingConstructor, i parametri al costruttore diventano importazioni. Per impostazione predefinita, quello che si sta importando (il nome del contratto) si basa sul tipo di parametro o una proprietà che vostro stanno importazione. Quindi in questo caso il tipo di contratto per entrambe le importazioni è stringa, e non c'è alcuna reale differenza tra il primo e il secondo parametro.

Sembra che si sta tentando di utilizzare le importazioni per la fornitura di valori di configurazione, che non è necessariamente quello che è stato progettato per. Per arrivare a fare ciò che si vuole, si dovrebbe ignorare il nome del contratto per ciascuno dei parametri, in questo modo:

[ImportingConstructor]
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version)
{ }

Allora avete bisogno di esportazioni per il metodo e la versione in vostro contenitore. Un modo per farlo è solo per aggiungere direttamente:

var container = new CompositionContainer(catalog);
container.ComposeExportedValue("Method", "MethodValue");
container.ComposeExportedValue("Version", "2.0");
container.ComposeParts(this);

(Notare che ComposeExportedValue è in realtà un metodo di estensione definita sulla classe AttributedModelServices statico.)

Se volete leggere questi valori da un file di configurazione di qualche tipo, è possibile creare il proprio fornitore di esportazione che legge la configurazione e fornisce i valori in esso come le esportazioni verso il contenitore.

Un modo alternativo per gestire questa situazione potrebbe essere quella di importare solo un'interfaccia che fornisce l'accesso ai valori di configurazione per nome, e ottenere i valori necessari dal corpo del costruttore.

Altri suggerimenti

Mi piace la soluzione di Daniel; tuttavia, solo una cosa che vedo è l'accoppiamento stretto dei nomi dei parametri tra l'attore (che crea CompopositionContrainer ()) e parte di esportazione con [ImportingConstructor] per CTOR personalizzato. Ad esempio, "Metodo" ha due essere abbinati in entrambi i luoghi. Rende difficile mantenere la parte di esportazione, se l'attore e parte di esportazione sono in progetti di differenza.

Se è possibile, vorrei aggiungere il secondo CTOR alla classe parte di esportazione. Ad esempio:

[Export(typeof(BUsers))] 
public class EditProfile : BUsers
{
    [ImportingConstructor]
    public EditProfile(EditProfileParameters ctorPars)
    : this(ctorPars.Method, ctorPars.Version) {}

    public EditProfile(string Method, string Version)
    {
        Version = "2";
        Action = "Edit";
        TypeName = "EditProfile";
    }

La classe di EditProfileParameters dovrebbe essere semplice: due proprietà di metodo e di versione:

[Export]
public class EditProfileParameters{
   public string Method { get; set; }
   public string Version { get; set; }
}

Il punto chiave è quello di aggiungere l'attributo di esportazione alla classe. Poi MEF dovrebbe essere in grado di mappare questa classe per il parametro di CTOR di EditProfile.

Ecco ad esempio per aggiungere la parte Esporta in contenitore:

var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);

Anche se in ritardo al gioco, ecco un altro approccio che sfrutta una caratteristica meno noto del MEF: Esportazioni di proprietà

public class ObjectMother
{
    [Export]
    public static EditProfile DefaultEditProfile
    {
        get
        {
            var method = ConfigurationManager.AppSettings["method"];
            var version = ConfigurationManager.AppSettings["version"];

            return new EditProfile(method,version);
        }
    }
}

Non usi sono necessari per ObjectMother per far funzionare tutto questo, e non gli attributi sono obbligatori in EditProfile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top