Managed Extensibility Framework - Documentationの 第三回です。Declaring Exports を見ていきます。
ExportAttribute Class (System.ComponentModel.Composition) は、プロパティやメソッドにも付与出来るのですが、それのサンプルコードが載っています。
メソッドについては、MEF Programming Guide 1.Hosting MEF in an application を試してみた - お だ のスペース で試したので省略。
プロパティについては、こんな感じです。
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
public class Program
{
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
Console.ReadKey();
}
public void Run()
{
var i = new UsesTimeout();
Compose(i);
Console.WriteLine(i.Timeout);
Console.ReadKey();
}
private void Compose(UsesTimeout i)
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this, i);
}
}
public class Configuration
{
[Export("Timeout")]
public int Timeout
{
get { return 10; }
}
}
public class UsesTimeout
{
[Import("Timeout")]
public int Timeout { get; set; }
}
これで、Run メソッド内の Console.WriteLine(i.Timeout); で 10 が表示されます。ちなみにどういう動きをするのか気になってプロパティに対して set してみると色々見えてきた。
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
public class Program
{
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
Console.ReadKey();
}
public void Run()
{
var i = new UsesTimeout();
Compose(i);
Console.WriteLine(i._timeout); // 10
Console.WriteLine(i.Timeout); // 10
i.Timeout = 2; // set してみる。
Console.WriteLine(i._timeout); // 2
Console.WriteLine(i.Timeout); // 2
Console.ReadKey();
}
private void Compose(UsesTimeout i)
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
Console.WriteLine(i._timeout); // 0
container.ComposeParts(this, i);
Console.WriteLine(i._timeout); // 10
}
}
public class Configuration
{
[Export("Timeout")]
public int Timeout
{
get { return 10; }
}
}
public class UsesTimeout
{
public int _timeout;
[Import("Timeout")]
public int Timeout { get { return _timeout; } set { _timeout = value; } }
}
このコードを実行してみると、ComposeParts した際に、Export属性が付いているプロパティから値を取得し、Import属性が付いているプロパティに値を設定しているみたい。
プロパティの実装が置き換わるのでは無く、単に値だけ設定しているってことみたい。これは、以下のようにコードを書き換えても動くことからわかる。
public class UsesTimeout
{
[Import("Timeout")]
public int _timeout;
// [Import("Timeout")]
public int Timeout { get { return _timeout; } set { _timeout = value; } }
}
ちなみに、Non Public な物も指定可能と書いてある。
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
public class Program
{
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
Console.ReadKey();
}
public void Run()
{
var i = new UsesTimeout();
Compose(i);
i.Test();
Console.ReadKey();
}
private void Compose(UsesTimeout i)
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this, i);
}
}
public class Configuration
{
[Export("Timeout")]
private int Timeout
{
get { return 10; }
}
}
public class UsesTimeout
{
[Import("Timeout")]
private int Timeout { get; set; }
public void Test()
{
Console.WriteLine(Timeout);
}
}
但し、
MEF supports discovery of public and non-public Parts. You don't need to do anything to enable this behavior. Please note that in medium/partial trust environments (including Silverlight) non-public composition will not be supported.
Silverlight等の部分信頼な環境ではサポートしていませんって書いてるのかな?今度、Silverlight でも試してみる。