MEF Constructor Injection

Próbuję rozgryźć atrybut wtrysku konstruktora MEF. Nie mam pojęcia, jak to powiedzieć, aby załadować parametry konstruktora.

To jest właściwość, którą próbuję załadować

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

Oto kod, którego używam do importowania zestawów.

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

Oto klasa, którą próbuję załadować

[Serializable]
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
    [ImportingConstructor]
    public EditProfile(string Method, string Version)
    {            
        Version = "2";
        Action = "Edit";
        TypeName = "EditProfile";
    }
Author: valdetero, 2010-01-05

3 answers

Gdy używasz atrybutu ImportingConstructor, parametry do konstruktora stają się importami. Domyślnie importowany element (nazwa umowy) zależy od typu parametru lub właściwości, do których importowany jest element. Tak więc w tym przypadku typem umowy dla obu importów jest string i nie ma rzeczywistej różnicy między pierwszym i drugim parametrem.

Wygląda na to, że próbujesz użyć importu do dostarczenia wartości konfiguracyjnych, co niekoniecznie jest tym, co został zaprojektowany dla. Aby uzyskać to, co chcesz, powinieneś nadpisać nazwę kontraktu dla każdego z parametrów, jak poniżej:

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

Następnie musisz eksportować metodę i wersję w kontenerze. Jednym ze sposobów, aby to zrobić, jest po prostu dodać je bezpośrednio:

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

(zauważ, że ComposeExportedValue jest w rzeczywistości metodą rozszerzenia zdefiniowaną w klasie Static AttributedModelServices.)

Jeśli chcesz odczytać te wartości z jakiegoś pliku konfiguracyjnego, możesz utworzyć Twój własny dostawca eksportu, który odczytuje konfigurację i dostarcza wartości w niej jako eksport do kontenera.

Alternatywnym sposobem radzenia sobie z tym byłoby zaimportowanie interfejsu, który zapewnia dostęp do wartości konfiguracyjnych po nazwie i pobranie potrzebnych wartości z ciała konstruktora.

 55
Author: Daniel Plaisted,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-02 10:42:47

Podoba mi się rozwiązanie Daniela; jednak jedyną rzeczą, którą widzę, jest ścisłe powiązanie nazw parametrów między aktorem (który tworzy CompopositionContrainer()) i eksportem części za pomocą [ImportingConstructor] dla niestandardowego CTOR. Na przykład, "metoda" ma dwa być dopasowane w obu miejscach. Trudno jest utrzymać część eksportową, jeśli aktor i część eksportowa są w projektach różnicowych.

Jeśli to możliwe, dodałbym drugi CTOR do klasy części eksportowej. Na przykład:

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

Klasa EditProfileParameters powinna być prosta: dwie właściwości metody i wersji:

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

Kluczowym punktem jest dodanie atrybutu Export do klasy. Następnie MEF powinien być w stanie zmapować tę klasę do parametru ctor EditProfile.

Oto przykład dodania części eksportowej do kontenera:

var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);
 23
Author: David.Chu.ca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-02 23:41:27

Mimo późnej wersji gry, oto inne podejście, które wykorzystuje mniej znaną funkcję MEF: eksport Nieruchomości

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

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

Do działania tego obiektu nie są wymagane żadne zastosowania, a atrybuty nie są wymagane w EditProfile.

 0
Author: bryanbcook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-05 17:16:40