Как создать экземпляр объекта MEF, используя Ninject? - PullRequest
10 голосов
/ 07 сентября 2010

Мое приложение использует 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модуль в основной сборке, а не сборка, в которой они находятся)

Ответы [ 2 ]

6 голосов
/ 10 сентября 2010

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

kernel.GetAll<IMyInterface>()

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

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

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

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

РЕДАКТИРОВАТЬ: Вв этом случае вы хотите привязку, которая имеет:

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

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

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

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

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

0 голосов
/ 08 сентября 2010

Вы можете использовать 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() без метаданных

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

...