我使用无属性方法来配置MEF
我读了以下文章:
http://msdn.microsoft.com/en-us/magazine/jj133818.aspx
http://blogs.microsoft.co.il/blogs/bnaya/archive/2013/01/12/mef-2-0-mini-series-part-4-fluent-import.aspx
测试代码(控制台应用程序项目,.NET 4.5):
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using System.Linq;
namespace MEF2
{
public interface IPlugin
{
void Run();
}
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class PluginMetadataAttribute : ExportAttribute, IPluginMetadata
{
public string Name { get; set; }
public string Version { get; set; }
public PluginMetadataAttribute(string name, string version)
: base(typeof(IPlugin))
{
Name = name;
Version = version;
}
}
[PluginMetadata("Plugin1", "1.0.0.0")]
public class Plugin1 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
[PluginMetadata("Plugin2", "2.0.0.0")]
public class Plugin2 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin2 runed");
}
}
class Program
{
CompositionContainer container;
IEnumerable<Lazy<IPlugin, IPluginMetadata>> plugins = Enumerable.Empty<Lazy<IPlugin, IPluginMetadata>>();
static void Main(string[] args)
{
var program = new Program();
foreach (var plugn in program.plugins) {
Console.WriteLine("{0}, {1}", plugn.Metadata.Name, plugn.Metadata.Version);
plugn.Value.Run();
}
}
Program()
{
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>();
builder
.ForType<Program>()
.Export()
.ImportProperties<IPlugin>(
propertyFilter => true,
(propertyInfo, importBuilder) => {
importBuilder.AsMany();
}
);
var catalog = new AggregateCatalog(
new AssemblyCatalog(typeof(Program).Assembly, builder)
);
container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
出口工作正常
但是当我尝试导入许多它不起作用。
请帮我解决这个问题。
答案 0 :(得分:1)
这不是属性免费(命令性)方法,因为导出是归因的(声明性的)。您的自定义元数据属性派生自ExportAttribute
。
要使此代码生效,您需要执行以下操作:
AssemblyCatalog
。如果没有这个,就无法使用注册构建器。Lazy<IPlugin, IPluginMetadata>
更新基于约定的导入,因为这是导出的内容。ComposeParts
的来电替换为GetExports
。更新的构造函数代码为:
var builder = new RegistrationBuilder();
builder
.ForType<Program>()
.Export()
.ImportProperties<Lazy<IPlugin, IPluginMetadata>>(
propertyFilter => true,
(propertyInfo, importBuilder) =>
{
importBuilder.AsMany();
}
);
var catalog = new AggregateCatalog(
new AssemblyCatalog(typeof(Program).Assembly, builder)
);
container = new CompositionContainer(catalog);
//container.ComposeParts(this);
plugins = container.GetExports<IPlugin, IPluginMetadata>();
我不确定如何使用ComposeParts
进行此操作。我来看看吧。此外,自定义元数据不必派生自ExportAttribute
。它可以来自System.Attribute
。这也可以帮助您进行必要的导出。
答案 1 :(得分:1)
谢谢,我找到了解决这个问题的方法 奇怪的是,我从来没有找到这样的例子 示例代码:
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
namespace MEF2
{
public interface IPlugin
{
void Run();
}
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class PluginMetadataAttribute : ExportAttribute, IPluginMetadata
{
public string Name { get; set; }
public string Version { get; set; }
public PluginMetadataAttribute(string name, string version)
: base(typeof(IPlugin))
{
Name = name;
Version = version;
}
}
[PluginMetadata("Plugin1", "1.0.0.0")]
public class Plugin1 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
[PluginMetadata("Plugin2", "2.0.0.0")]
public class Plugin2 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin2 runed");
}
}
public class PluginStore
{
public IEnumerable<Lazy<IPlugin, IPluginMetadata>> Plugins { get; private set; }
}
class Program
{
static void Main(string[] args)
{
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>();
builder
.ForType<PluginStore>()
.Export()
.ImportProperties(
propertyFilter => true,
(propertyInfo, importBuilder) => {
importBuilder.AsMany();
}
);
var catalog = new AssemblyCatalog(typeof(PluginStore).Assembly, builder);
using (var container = new CompositionContainer(catalog)) {
var pluginStore = container.GetExport<PluginStore>().Value;
foreach (var plugin in pluginStore.Plugins) {
Console.WriteLine("{0}, {1}", plugin.Metadata.Name, plugin.Metadata.Version);
plugin.Value.Run();
}
}
}
}
}