составление частей MEF в C # как простой контейнер Funq - PullRequest
0 голосов
/ 09 сентября 2011

В Funq и, возможно, в большинстве других IoC-контейнеров. Я могу просто сделать это, чтобы настроить тип:

container.Register<ISomeThing>(c => new SomeThing());

Как можно быстро расширить MEF (или использовать существующие функции MEF) длясделайте то же самое без использования атрибутов.

Вот как я думал, что смогу сделать это:

var container = new CompositionContainer();
var batch = new CompositionBatch();
batch.AddExport<ISomeThing>(() => new SomeThing());
batch.AddExportedValue(batch);
container.Compose(batch);

С этим методом расширения для CompositionBatch:

public static ComposablePart AddExport<TKey>(this CompositionBatch batch, Func<object> func)
{
    var typeString = typeof(TKey).ToString();
    return batch.AddExport(
        new Export(
            new ExportDefinition(
                typeString, 
                new Dictionary<string, object>() { { "ExportTypeIdentity", typeString } }),
            func));

}

Если я позже сделаю:

var a = container.GetExport<ISomeThing>().Value;
var b = container.GetExport<ISomeThing>().Value;

Оба экземпляра одинаковы.Как я могу заставить (настроить) их на разные экземпляры?

Если это не тот путь, как мне это сделать в MEF?

Ответы [ 4 ]

1 голос
/ 09 сентября 2011

Если вы не хотите использовать атрибуты, вы можете использовать этот трюк (на основе поста Марка Симанна ).

Сначала создайте общий класс, подобный этому:

[PartCreationPolicy(CreationPolicy.NonShared)]
public class MefAdapter<T> where T : new()
{
    private readonly T export;

    public MefAdapter()
    {
        this.export = new T();
    }

    [Export]
    public virtual T Export
    {
        get { return this.export; }
    }
}

Теперь вы можете зарегистрировать любой класс в контейнере, например:

var registeredTypesCatalog = new TypeCatalog(
    typeof(MefAdapter<Foo>),
    typeof(MefAdapter<Bar>), 
    ...);
var container = new CompositionContainer(catalog);

В качестве альтернативы, вы можете реализовать свой собственный поставщик экспорта, полученный из ExportProvider , который позволяет вам в значительной степени дублировать способ работы Funq:

var provider = new FunqyExportProvider();
provider.Register<IFoo>(context => new Foo());
var container = new CompositionContainer(provider);
1 голос
/ 09 сентября 2011

Я думаю, что ключом является добавление делегата в контейнер, например:

container.AddExportedValue<Func<ISomething>>(() => new Something());

Таким образом, вы можете захватить делегат и выполнить его:

var factory = container.GetExport<Func<ISomething>>();
ISomething something = factory();

КонечноMEF (Silverlight) предоставляет собственный тип ExportFactory<T>ExportFactory<T,TMetadata>), который поддерживает создание новых экземпляров для каждого вызова импорта. Вы можете добавить поддержку для этого, загрузив файл Glen Block ExportFactory для .NET 4.0 (Настольная) библиотека .

0 голосов
/ 09 сентября 2011

В каталоге Skydrive Глена Блока, указанном в Ответ Мэтью Эббота Я нашел что-то простое и легкое: A FuncCatalog. Загрузите его здесь: FuncCatalogExtension .

Используя несколько маленьких классов из этого проекта, я теперь мог сделать это:

var funcCatalog = new FuncCatalog();
funcCatalog.AddPart<ISomeThing>(ep => new SomeThing());
var container = new CompositionContainer(funcCatalog);
var batch = new CompositionBatch();
batch.AddExportedObject<ExportProvider>(container);
container.Compose(batch);

var a = container.GetExportedObject<ISomeThing>();
var b = container.GetExportedObject<ISomeThing>();
0 голосов
/ 09 сентября 2011

Оба экземпляра одинаковы.Как я могу заставить (настроить) их на разные экземпляры?

Просто отметьте класс SomeThing следующим образом:

[Export(typeof(ISomeThing)]
[PartCreationPolicy(CreationPolicy.NonShared]
public class SomeThing : ISomeThing
{
   ...
}

И тогда вы получите разные экземпляры, где бы вы ни находилисьimport ISomeThing.

В качестве альтернативы вы также можете установить необходимую политику создания для импорта:

[Export(typeof(IFoo))]
public class Foo : IFoo
{
   [Import(typeof(ISomeThing), 
       RequiredCreationPolicy = CreationPolicy.NonShared)]
   public ISomething SomeThing { private get; set; }

}
...