MEF 2:导入很多

时间:2013-01-17 09:45:10

标签: c# .net mef

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

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

2 个答案:

答案 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();
                }
            }
        }
    }
}
相关问题