MEF-导入词典
MEF-Import into Dictionary
我目前正在重构一个应用程序,想引入 MEF。
Export class (class Apple) 完成并标有 Export-keyword...
在导入站点上,我目前有一个初始化如下所示的字典:
Dictionary<int, Apple> dict = new Dictionary<int, Apple>();
for(int i=0; i < 10; i++)
dict.add(i, new Apple());
...
如何使用 MEF 初始化字典?
所以我认为你的问题可以归结为,"How to I ensure that the container produces multiple instances of an object rather than reusing the same object every time it's requested." 嗯,这很简单——你只需要指定 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();
}
}
我目前正在重构一个应用程序,想引入 MEF。 Export class (class Apple) 完成并标有 Export-keyword... 在导入站点上,我目前有一个初始化如下所示的字典:
Dictionary<int, Apple> dict = new Dictionary<int, Apple>();
for(int i=0; i < 10; i++)
dict.add(i, new Apple());
...
如何使用 MEF 初始化字典?
所以我认为你的问题可以归结为,"How to I ensure that the container produces multiple instances of an object rather than reusing the same object every time it's requested." 嗯,这很简单——你只需要指定 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();
}
}