My previous post contains attempt use attribute-free (convention based) approach to configure MEF: MEF 2: import many.
But it contains export metadata attribute usage in the class PluginMetadataAttribute needed for lazy initialization plugin by condition (specific name, version).
How to get rid of ExportAttribute dependency?
2 に答える
私は3つの解決策を見つけました。
解決策 1 (クラス定数フィールドを使用する、不十分な解決策):
public class Plugin1 : IPlugin
{
public const string Name = "Plugin1";
public const string Version = "1.0.0.0";
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
// ...
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetField("Name").GetRawConstantValue());
exportBuilder.AddMetadata("Version", t => t.GetField("Version").GetRawConstantValue());
});
解決策 2 (クラス プロパティを使用する、不適切な解決策):
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
public interface IPlugin : IPluginMetadata
{
void Run();
}
public class Plugin1 : IPlugin
{
public string Name { get { return "Plugin 1"; } }
public string Version { get { return "1.0.0.0"; } }
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
そして、これを説明した方法でプロパティ値を取得します: https://stackoverflow.com/a/11162876/1986524
解決策 3 (属性を使用します。より良いが、すべてが満足というわけではありません):
using System;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using System.Reflection;
namespace MEF2
{
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
public interface IPlugin
{
void Run();
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginMetadataAttribute : Attribute, IPluginMetadata
{
public string Name { get; set; }
public string Version { get; set; }
public PluginMetadataAttribute(string name, string version)
{
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
{
static void Main(string[] args)
{
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetCustomAttribute<PluginMetadataAttribute>().Name);
exportBuilder.AddMetadata("Version", t => t.GetCustomAttribute<PluginMetadataAttribute>().Version);
});
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), builder);
using (var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection)) {
var plugins = container.GetExports<IPlugin, IPluginMetadata>();
foreach (var plugin in plugins) {
Console.WriteLine("{0}, {1}", plugin.Metadata.Name, plugin.Metadata.Version);
plugin.Value.Run();
}
}
}
}
}
ソリューション 3 には、このコードに問題が含まれています。
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetCustomAttribute<PluginMetadataAttribute>().Name);
exportBuilder.AddMetadata("Version", t => t.GetCustomAttribute<PluginMetadataAttribute>().Version);
})
問題:
- メタデータが欠落している場合、メタデータの追加をキャンセルできません
- 重複コード
t.GetCustomAttribute<PluginMetadataAttribute>()
Export<>
提供されていないフィルター
誰かが他の解決策を知っているなら、書いてください。
他の質問で参照しているMEF の構成への属性を使用しないアプローチには、属性を使用せずにメタデータを追加する方法の例が含まれています。
この例は、パラメータとしてを取り、オーバーロードの 1 つを使用して特定のエクスポートのメタデータを追加するPartBuilder.ExportPropertiesオーバーロードの使用方法を示しています。Action<PropertyInfo, ExportBuilder>
ExportBuilder.AddMetadata
メタデータを追加する方法はこれだけではありません。PartBuilderのすべてのエクスポート メソッドには、ExportBuilder パラメータAction<>
を持つ(または Action<,>) を取るオーバーロードがあります。これらのオーバーロードを使用して、同様の方法でメタデータを追加できます。