2

我使用无属性方法来配置 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);
        }
    }
}

出口工作正常。
但是当我尝试导入很多时它不起作用。
请帮我解决这个问题。

4

2 回答 2

1

这不是无属性(命令式)方法,因为导出是属性式(声明式)。您的自定义元数据属性派生自ExportAttribute.

要使此代码正常工作,您需要执行以下操作:

  • 从构造函数代码中删除命令式导出。
  • 将注册生成器传递给AssemblyCatalog. 没有这个,注册生成器将无法使用。
  • 更新基于约定的导入,Lazy<IPlugin, IPluginMetadata>因为这是要导出的内容。
  • 将调用替换ComposePartsGetExports

更新的构造函数代码是:

            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. 这也将让你有一个必要的出口。

于 2013-01-18T01:29:23.703 回答
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();
                }
            }
        }
    }
}
于 2013-01-18T13:51:23.897 回答