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>これがエクスポートされるものであるため、コンベンションベースのインポートを更新します。
  • 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。これにより、命令的なエクスポートも可能になります。

于 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 に答える