wake-up-neo.net

MEF-Konstruktorinjektion

Ich versuche, das Konstruktionsinjektionsattribut von MEF herauszufinden. Ich habe keine Ahnung, wie ich es sage, die Parameter des Konstruktors zu laden.

Dies ist die Eigenschaft, die ich laden möchte

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

Hier ist der Code, den ich zum Importieren der Baugruppen verwende.

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);
}

Hier ist die Klasse, die ich laden möchte

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

Wenn Sie das ImportingConstructor-Attribut verwenden, werden die Parameter für den Konstruktor zu Importen. Standardmäßig basiert das, was Sie importieren (den Vertragsnamen), auf dem Typ des Parameters oder der Eigenschaft, in den Sie importieren. In diesem Fall ist der Vertragstyp für beide Importe eine Zeichenfolge, und es gibt keinen wirklichen Unterschied zwischen dem ersten und dem zweiten Parameter.

Es sieht so aus, als würden Sie versuchen, Importwerte zu verwenden, um Konfigurationswerte bereitzustellen. Dies ist nicht unbedingt das, für das sie entwickelt wurden. Damit es das tut, was Sie möchten, sollten Sie den Vertragsnamen für jeden Parameter wie folgt überschreiben:

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

Dann benötigen Sie Exporte für Methode und Version in Ihrem Container. Eine Möglichkeit, dies zu tun, besteht darin, sie direkt hinzuzufügen:

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

(Beachten Sie, dass ComposeExportedValue eine Erweiterungsmethode ist, die in der statischen AttributedModelServices-Klasse definiert ist.)

Wenn Sie diese Werte aus einer Konfigurationsdatei lesen möchten, können Sie einen eigenen Exportanbieter erstellen, der die Konfiguration liest und die darin enthaltenen Werte als Export in den Container bereitstellt.

Alternativ können Sie einfach eine Schnittstelle importieren, die den Zugriff auf die Konfigurationswerte über den Namen ermöglicht, und die erforderlichen Werte aus dem Rumpf des Konstruktors abrufen.

55
Daniel Plaisted

Ich mag Daniels Lösung. Ich sehe jedoch nur eine enge Verknüpfung von Parameternamen zwischen dem Akteur (der CompopositionContrainer () erstellt) und dem Export-Teil mit [ImportingConstructor] für benutzerdefinierte CTOR. Zum Beispiel muss "Method" an beiden Stellen zwei übereinstimmen. Es ist schwierig, den Exportteil beizubehalten, wenn sich der Akteur und der Exportteil in unterschiedlichen Projekten befinden.

Wenn es möglich ist, würde ich die zweite CTOR zur Export-Teileklasse hinzufügen. Zum Beispiel:

[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";
    }

Die Klasse von EditProfileParameters sollte unkompliziert sein: zwei Eigenschaften von Method und Version:

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

Der Schlüsselpunkt ist, der Klasse Exportattribute hinzuzufügen. Dann sollte MEF diese Klasse dem Parameter von CTOR von EditProfile zuordnen können.

Hier ein Beispiel zum Hinzufügen des Exportteils zum Container:

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

Obwohl es erst spät im Spiel ist, gibt es einen anderen Ansatz, der eine weniger bekannte Funktion von MEF nutzt: Eigenschaftenexporte

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

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

Damit ObjectMother funktioniert, sind keine Verwendungen erforderlich, und für EditProfile sind keine Attribute erforderlich.

0
bryanbcook