<< 【MEF】ImportDefinition.IsConstraintSatisfiedBy メソッド | main | 【MEF】(仮)リフレクション べース プログラミング モデル。 >>

【MEF】自作カタログ 絶対真似しないでください危険です。

JUGEMテーマ:コンピュータ

Source and Project


※当Blogの最近のMEFの投稿はMEFフレームワークを必ずしも正しい使い方をしているとは限りませんので注意してください。

ComposablePartCatalog クラス、ComposablePartDefinition クラス、ComposablePart クラスを使用して自作カタログを作成しました。クラスのそれぞれの責務はMSDNライブラリーによると

-------------------
ComposablePartCatalog クラス
ComposablePartDefinition オブジェクトを収集して返すコンポーザブル パーツ カタログの抽象基本クラスを表します。

ComposablePartDefinition クラス
ComposablePart オブジェクトの作成を記述して有効にするコンポーザブル パーツ定義の抽象基本クラスを定義します。

ComposablePart クラス
オブジェクトをインポートしたり、エクスポートされたオブジェクトを生成したりするコンポーザブル パーツの抽象基本クラスを定義します。
--------------------

カタログを自作したり拡張したい場合にすべてをこれらの抽象クラスから直接継承する必要は全くないと思いますが、これらの抽象クラスのメンバーがいつ呼ばれるのかシーケンスが知りたいのと、属性付きプログラミング モデル以外でも実装可能なことを試してみたいなど、いろいろやってみたいことがあったので、実装してみました。

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Primitives;
using System.Linq;

namespace Art55.MEF.JunkLib
{
    public class MyComposablePartCatalog : ComposablePartCatalog
    {
        public MyComposablePartCatalog(params Type[] types)
        {
            _partDefinitionList = new List<ComposablePartDefinition>();
            foreach (Type type in types)
            {
                _partDefinitionList.Add(new MyComposablePartDefinition(type));
            }
        }

        public override IQueryable<ComposablePartDefinition> Parts
        {
            get { return _partDefinitionList.AsQueryable(); }
        }

        private readonly List<ComposablePartDefinition> _partDefinitionList;
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using System.Reflection;

namespace Art55.MEF.JunkLib
{
    class MyComposablePartDefinition : ComposablePartDefinition
    {
        public MyComposablePartDefinition(Type type)
        {
            _type = type;
            var metadata = new Dictionary<string, object>();
            metadata[CompositionConstants.ExportTypeIdentityMetadataName] =
                AttributedModelServices.GetTypeIdentity(type);
            _rootExportDefinition = new ExportDefinition(AttributedModelServices.GetContractName(type), metadata);
            _exportDefinitionList = new List<ExportDefinition> { _rootExportDefinition };
            _importDefinitionList = new Dictionary<ImportDefinition, PropertyInfo>();
            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                if (propertyInfo.CanWrite)
                {
                    Type importType = propertyInfo.PropertyType;
                    var importDefinition = new ContractBasedImportDefinition(
                        AttributedModelServices.GetContractName(importType),
                        AttributedModelServices.GetTypeIdentity(importType),
                        Enumerable.Empty<KeyValuePair<string, Type>>(),
                        ImportCardinality.ExactlyOne,
                        false,
                        false,
                        CreationPolicy.Shared);
                    _importDefinitionList.Add(importDefinition, propertyInfo);
                }
            }
        }

        public override IEnumerable<ExportDefinition> ExportDefinitions
        {
            get { return _exportDefinitionList; }
        }

        public override IEnumerable<ImportDefinition> ImportDefinitions
        {
            get { return _importDefinitionList.Keys; }
        }

        public override ComposablePart CreatePart()
        {
            return new MyComposablePart(this);
        }

        public Export CreateExport()
        {
            return new Export(_rootExportDefinition, () => Activator.CreateInstance(_type));
        }

        internal void SetImport(object obj, ImportDefinition importDefinition, Export export)
        {
            if (_importDefinitionList.ContainsKey(importDefinition))
            {
                PropertyInfo propertyInfo = _importDefinitionList[importDefinition];
                propertyInfo.SetValue(obj, export.Value, null);
            }
        }

        private readonly Type _type;
        private readonly ExportDefinition _rootExportDefinition;
        private readonly List<ExportDefinition> _exportDefinitionList;
        private readonly Dictionary<ImportDefinition, PropertyInfo> _importDefinitionList;
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Primitives;
using System.Linq;

namespace Art55.MEF.JunkLib
{
    class MyComposablePart : ComposablePart
    {
        public MyComposablePart(MyComposablePartDefinition definition)
        {
            if (definition == null)
                throw new ArgumentNullException("definition");

            _definition = definition;
        }

        public override IEnumerable<ExportDefinition> ExportDefinitions
        {
            get { return _definition.ExportDefinitions; }
        }

        public override IEnumerable<ImportDefinition> ImportDefinitions
        {
            get { return _definition.ImportDefinitions; }
        }

        public override object GetExportedValue(ExportDefinition definition)
        {
            if (_definition.Equals(definition))
                throw new ArgumentException("definition");

            object result = _definition.CreateExport().Value;
            foreach (ImportDefinition importDefinition in _importSetting.Keys)
            {
                if (_importSetting.ContainsKey(importDefinition) && _importSetting[importDefinition].Count() == 1)
                {
                    _definition.SetImport(result, importDefinition, _importSetting[importDefinition].First());
                }
            }
            return result;
        }

        public override void SetImport(ImportDefinition definition, IEnumerable<Export> exports)
        {
            _importSetting[definition] = exports;
        }

        private readonly Dictionary<ImportDefinition, IEnumerable<Export>> _importSetting = new Dictionary<ImportDefinition, IEnumerable<Export>>();
        private readonly MyComposablePartDefinition _definition;
    }
}

これらのクラスを使用してカタログを作成すると

指定したTypeは必ずExportとなり、publicなGetterが存在するプロパティは必ずImportとして設定されます。そして、Exportからインスタンスを作成時にインジェクションされます。実際のライブラリーを使用してインスタンスを作成するコードを書いてみると

using System;
using System.ComponentModel.Composition.Hosting;
using Art55.MEF.JunkLib;

namespace Art55.MEFSample20100525_001
{
    class Program
    {
        static void Main(string[] args)
        {
            var types = new[] {typeof (B), typeof (A), typeof (C)};
            var catalog = new MyComposablePartCatalog(types);
            var container = new CompositionContainer(catalog);
            A a = container.GetExportedValue<A>();
            a.Say();
        }
    }

    public class A
    {
        public B BObject { private get; set; }
        public void Say()
        {
            BObject.Say();
        }
    }

    public class B
    {
        public C CObject { private get; set; }
        public void Say()
        {
            CObject.Say();
        }
    }

    public class C
    {
        public void Say()
        {
            Console.WriteLine("C Say");
        }
    }
}

実行すると

C Say

と出力されます。一応、属性指定なしにExportやImportが指定可能なカタログが作成できました。

Source and Project



コメント
コメントする









この記事のトラックバックURL
トラックバック
calendar
   1234
567891011
12131415161718
19202122232425
2627282930  
<< September 2010 >>
あわせて読みたい
あわせて読みたいブログパーツ
selected entries
categories
archives
recent comment
recent trackback
recommend
キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。
recommend
ビジュアライジング・データ ―Processingによる情報視覚化手法
ビジュアライジング・データ ―Processingによる情報視覚化手法 (JUGEMレビュー »)
Ben Fry
javaぽい言語Processingを用いたビジュアライジングデータ。タイトルの通りいかにデータを視覚化するかというところを解説した本、手法やプロセスに対して丁寧でかつ具体的な例を挙げているのでわかりやすく、また応用が利きます。すばらしい本です。
recommend
recommend
recommend
recommend
recommend
recommend
Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰
recommend
recommend
recommend
Design rule index―デザイン、新・100の法則
Design rule index―デザイン、新・100の法則 (JUGEMレビュー »)
William Lidwell,Kritina Holden,Jill Butler
ユーザインターフェイス、ユーザビリティなどを考えたいならこの本をヒントにしてみるのも良いかと思います。
recommend
リファクタリング―プログラムの体質改善テクニック (Object Technology Series)
リファクタリング―プログラムの体質改善テクニック (Object Technology Series) (JUGEMレビュー »)
マーチン ファウラー,Martin Fowler,児玉 公信,平澤 章,友野 晶夫,梅沢 真史
Javaで書かれていますが、良本です。言語を覚えたら、まずこの本を読んでみましょう。
recommend
集合知プログラミング
集合知プログラミング (JUGEMレビュー »)
Toby Segaran
・・・挫折中の一本。
recommend
C#ではじめるWebサービスプログラミング
C#ではじめるWebサービスプログラミング (JUGEMレビュー »)
山崎 秀,笠原 一浩
動くモノが作れるから楽しい、この本で実現しましょう!
recommend
C#クックブック 第3版
C#クックブック 第3版 (JUGEMレビュー »)
Jay Hilyard,Stephen Teilhet
C#2.0からの移行を考えているならこの本がお勧めです。
recommend
LINQテクノロジ入門~Microsoft Visual Studio 2008による新たなクエリ構築技法~ (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ)
LINQテクノロジ入門~Microsoft Visual Studio 2008による新たなクエリ構築技法~ (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (JUGEMレビュー »)
赤間信幸
LINQ最強の入門本です。LINQの処理をイメージをわかりやすく解説されています。また、著者の赤間さんはわかりやすい解説をされることで超有名です。
recommend
Pro LINQ: Language Integrated Query in C# 2008 (Windows.Net)
Pro LINQ: Language Integrated Query in C# 2008 (Windows.Net) (JUGEMレビュー »)
Jr. Rattz Joseph C.
LINQをしっかり学びたい方にお勧めします。
recommend
recommend
WPF Recipes in C# 2008: A Problem-Solution Approach (Expert's Voice in .Net)
WPF Recipes in C# 2008: A Problem-Solution Approach (Expert's Voice in .Net) (JUGEMレビュー »)
Sam Noble,Sam Bourton,Allen Jones
WPFの基礎を一通り学習したら、この本を手に取りましょう。WPFのHowToやDeepな情報を得ることが出来ます。かなりお勧めです。
(注意:サンプルコードのレイアウト設計は間違ってるので注意です)
links
profile
search this site.
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM
JUGEMのブログカスタマイズ講座