簡體   English   中英

MEF-導入字典

[英]MEF-Import into Dictionary

Iam當前正在重構應用程序,並希望引入MEF。 Export類(Apple類)已完成,並用Export-keyword標記...在導入站點上,我目前有一個字典,其初始化如下所示:

Dictionary<int, Apple> dict = new Dictionary<int, Apple>();
for(int i=0; i < 10; i++)
    dict.add(i, new Apple());

...

如何使用MEF初始化字典?

因此,我認為您的問題可以歸結為:“如何確保容器產生一個對象的多個實例,而不是每次請求都重復使用同一對象。” 嗯,這很容易-您只需指定CreationPolicy.NonShared

考慮一下IApple示例實現:

public interface IApple { }

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IApple))]
public class Apple : IApple 
{ 
    private static int appleCounter = 0;
    private int id;

    public Apple() 
    {
        this.id = ++appleCounter;
    }

    public override string ToString()
    {
        return "Apple #" + this.id.ToString();
    }
}

這是您可能使用它的一種方式:

class Program
{
    public static void Main(string[] args)
    {
        var catalog = new ApplicationCatalog();
        var container = new CompositionContainer(catalog);
        IDictionary<int, IApple> dict = new Dictionary<int, IApple>();
        for (int i = 0; i < 10; i++)
        {
            dict.Add(i, container.GetExportedValue<IApple>());
        }

        foreach (var pair in dict)
        {
            Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
        }
    }
}

此處的代碼關鍵行是[PartCreationPolicy(CreationPolicy.NonShared)] 如果沒有這一點,將只有一個Apple被創造出來。 當然,這並不像您期望的那樣有用。 這是生成字典的另一種方法,該方法更加靈活:

public interface IBasket
{
    IDictionary<int, IApple> GetAppleDictionary();
}

[Export(typeof(IBasket))]
public class Basket : IBasket
{
    private IDictionary<int, IApple> dict;

    [ImportingConstructor]
    public Basket([Import] CompositionContainer container)
    {
        this.dict = new Dictionary<int, IApple>();
        for (int i = 0; i < 10; i++)
        {
            this.dict.Add(i, container.GetExportedValue<IApple>());
        }
    }

    public IDictionary<int, IApple> GetAppleDictionary()
    {
        return dict;
    }
}

class Program
{
    [Import(typeof(IBasket))]
    private IBasket basket = null;

    public static void Main(string[] args)
    {
        var program = new Program();
        program.Run();
    }

    private void Run()
    {
        var catalog = new ApplicationCatalog();
        var container = CreateCompositionContainer(catalog);
        container.ComposeParts(this);
        foreach (var pair in this.basket.GetAppleDictionary())
        {
            Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
        }
    }

    private static CompositionContainer CreateCompositionContainer(ComposablePartCatalog catalog)
    {
        var wrappedCatalog = new AggregateCatalog(catalog, new TypeCatalog(typeof (CompositionContainer)));
        var container = new CompositionContainer(wrappedCatalog);
        container.ComposeExportedValue(container);

        return container;
    }
}

這里最棘手的部分是CreateCompositionContainer 此方法確保CompositionContainer本身可用於滿足其所組成對象的導入。 這樣一來, Basket可以直接操縱容器來生成所需的所有蘋果。

只是出於演示目的,這是您還可以使用[ImportMany]屬性完成類似操作的一種方法(盡管所有這些[Export]確實讓我畏縮了):

public interface IApple { }

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IApple))]
[Export(typeof(IApple))]
/* ..repeat N times.. */
[Export(typeof(IApple))]
public class Apple : IApple 
{ 
    private static int appleCounter = 0;
    private int id;

    public Apple() 
    {
        this.id = ++appleCounter;
    }

    public override string ToString()
    {
        return "Apple #" + this.id.ToString();
    }
}

class Program
{
    [ImportMany(typeof(IApple))]
    private IEnumerable<IApple> apples = null;

    public static void Main(string[] args)
    {
        var program = new Program();
        program.Run();
    }

    void Run()
    {
        var catalog = new AssemblyCatalog(this.GetType().Assembly);
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
        apples.Dump();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM