Подтвердить что ты не робот

Как создать экземпляр экспортированного объекта MEF с помощью Ninject?

Мое приложение использует MEF для экспорта некоторых классов из внешней сборки. Эти классы настраиваются для инсталляции конструктора. Проблема, с которой я сталкиваюсь, заключается в том, что MEF пытается создать экземпляр классов, когда я пытаюсь получить к ним доступ. Есть ли способ, чтобы Ninject заботился о создании класса?

IEnumerable<Lazy<IMyInterface>> controllers = 
    mefContainer.GetExports<IMyInterface>();

// The following line throws an error because MEF is 
// trying to instantiate a class that requires 5 parameters
IMyInterface firstClass = controllers.First().Value;

Обновление:

Существует несколько классов, реализующих IMyInterface, и я хотел бы выбрать тот, у которого есть определенное имя, а затем создать Ninject экземпляр. Я не уверен, хочу ли я лень.

[Export(typeof(IMyInterface))]
public class MyClassOne : IMyInterface {

     private MyRepository one;
     private YourRepository two;

     public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
            one = repoOne;
            two = repoTwo;
     }         
}

[Export(typeof(IMyInterface))]
public class MyClassTwo : IMyInterface {

     private MyRepository one;
     private YourRepository two;

     public MyClassTwo(MyRepository repoOne, YourRepository repoTwo) {
            one = repoOne;
            two = repoTwo;
     }


}

Используя MEF, я хотел бы получить либо MyClassOne, либо MyClassTwo, а затем предоставить Ninject экземпляр MyRepository и YourRepository (примечание: эти два связаны в модуле Ninject в основной сборке и а не сборку, в которой они находятся)

4b9b3361

Ответ 1

Вы можете использовать механизм Ninject Load, чтобы получить экспортированные классы в микс, и вы либо:

kernel.GetAll<IMyInterface>()

Создание является ленивым (т.е. каждый impl IMyInterface создается "на лету", как вы перебираете выше) IIRC, но посмотрите на тесты в источник (это очень чистый и читаемый, у вас нет оправдания: P).

Если вам не нужна лента, используйте LINQ ToArray или ToList, чтобы получить IMyInterface[] или List<IMyInterface>

или вы можете использовать низкоуровневое семейство методов Resolve() (опять же, посмотрите в тестах для выборок), чтобы получить приемлемые сервисы [если вы хотите сделать некоторую фильтрацию или что-то другое, кроме как просто использовать экземпляр - хотя обязательные метаданные, вероятно, являются решением там]

Наконец, если вы можете редактировать в объяснении, нужна ли вам сама лени или делаете это, чтобы проиллюстрировать точку. (и искать здесь Lazy<T> здесь и вообще по Ninject и autofac для некоторых выборок - вспомните, если в источнике есть какие-либо примеры - не думайте, что все еще на 3.5)

EDIT: в этом случае требуется привязка, которая имеет:

Bind<X>().To<>().In...().Named( "x" );

в регистрах в ваших модулях в дочерней сборке.

Затем, когда вы разрешаете родительскую сборку, вы используете перегрузку Kernel.Get<>, которая принимает параметр name, чтобы указать тот, который вы хотите (нет необходимости в лени, массивах или IEnumerable). Механизм Named является специфическим (только одно или два вспомогательных расширения реализуют его в терминах обобщенной концепции) применения концепции метаданных привязки в Ninject - там достаточно места для его настройки, если недостаточно простого имени.

Если вы используете MEF для создания объектов, вы можете использовать механизм Kernel.Inject() для ввода свойств. Проблема в том, что либо MEF, либо Ninject  - должен найти типы (Ninject: обычно через Bind() в Module или через расширения сканирования, после чего можно сделать Resolve для подмножества привязок перед инстанцированием - хотя это не то, что вы обычно делаете)  - должен создавать экземпляры типов (Ninject: обычно через Kernel.Get(), но если вы обнаружили типы через, например, MEF, вы можете использовать перегрузки Kernel.Get(Type))  - должен вводить типы (Ninject: обычно через Kernel.Inject() или неявно в `Kernel.Get())

Что мне еще не ясно, почему вы чувствуете, что вам нужно смешивать и калечить два - в конечном счете, обязанности по совместному использованию во время строительства, а встраивание конструктора не является основным вариантом использования для любой библиотеки lib, даже если они являются вполне сложными библиотеками. У вас есть ограничение или у вас есть критические преимущества с обеих сторон?

Ответ 2

Вы можете использовать ExportFactory для создания экземпляров см. документы здесь:

http://mef.codeplex.com/wikipage?title=PartCreator

Ваше дело будет чересчур разным Я бы использовал метаданные и пользовательский атрибут

[ImportMany(AllowRecomposition=true)] 
    IEnumerable<ExportFactory<IMyInterFace, IMyInterfaceMetaData>> Controllers{ get; set; } 

public IMyInterface CreateControllerFor(string parameter)
{
var controller = Controllers.Where(v => v.Metadata.ControllerName == parameter).FirstOrDefault().CreateExport().Value; 
            return controller; 
}

или используйте return Controllers.First() без метаданных

Затем вы можете закодировать части ninject вокруг этого или даже придерживаться MEF Надеюсь, что это поможет