MEF Constructor Injection - PullRequest
       18

MEF Constructor Injection

39 голосов
/ 05 января 2010

Я пытаюсь выяснить атрибут MEF Constructor Injection. Я понятия не имею, как я говорю, чтобы загрузить параметры конструктора.

Это свойство, которое я пытаюсь загрузить

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

Вот код, который я использую для импорта сборок.

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

Вот класс, который я пытаюсь загрузить

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

Ответы [ 3 ]

55 голосов
/ 05 января 2010

Когда вы используете атрибут ImportingConstructor, параметры конструктора становятся импортом. По умолчанию то, что вы импортируете (имя контракта), основано на типе параметра или свойства, в которое вы импортируете. Таким образом, в этом случае тип контракта для обоих типов импорта - строка, и между первым и вторым параметром нет реальной разницы.

Похоже, вы пытаетесь использовать импорт для предоставления значений конфигурации, которые не обязательно предназначены для этого. Чтобы заставить его делать то, что вы хотите, вы должны переопределить имя контракта для каждого из параметров, например:

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

Тогда вам нужен экспорт для Method и Version в вашем контейнере. Один из способов сделать это - просто добавить их напрямую:

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

(Обратите внимание, что ComposeExportedValue на самом деле является методом расширения, определенным в статическом классе AttributedModelServices.)

Если вы хотите прочитать эти значения из какого-либо файла конфигурации, вы можете создать свой собственный поставщик экспорта, который считывает конфигурацию и предоставляет значения в ней как экспорт в контейнер.

Альтернативный способ справиться с этим - просто импортировать интерфейс, обеспечивающий доступ к значениям конфигурации по имени, и получить нужные значения из тела конструктора.

23 голосов
/ 21 января 2010

Мне нравится решение Даниэля; однако, я вижу только одну вещь - это тесная связь имен параметров между актером (который создает CompopositionContrainer ()) и частью экспорта с [ImportingConstructor] для настроенного CTOR. Например, «Метод» должен соответствовать двум в обоих местах. Сложно поддерживать часть экспорта, если актер и часть экспорта находятся в разных проектах.

Если это возможно, я бы добавил второй CTOR в класс детали экспорта. Например:

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

Класс EditProfileParameters должен быть простым: два свойства метода и версии:

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

Ключевым моментом является добавление атрибута экспорта в класс. Тогда MEF сможет отобразить этот класс на параметр CTOR в EditProfile.

Вот пример добавления части экспорта в контейнер:

var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);
1 голос
/ 05 октября 2015

Хотя и поздно к игре, вот еще один подход, который использует менее известную функцию MEF: Экспорт свойств

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

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

Для ObjectMother для этого не требуется использование, и атрибуты не требуются в EditProfile.

...