あなたが探しているものは、依存関係によって並べ替えることができると思います。私はアプリケーションの起動を管理するBootstrapperオブジェクトを作成したのと同じようなものを使用しました。このブートストラップは、0個以上のブートストラップタスクをサポートします。これらのタスクには、依存関係がある場合とない場合があります。私がこれに取り組んだのは、新しいコレクション型のDependencyList<TModel, TKey>
を作成して、任意の数の項目を追加できるようにし、最初の列挙時または後続のコレクション変更後に自動的に並べ替えます。
あなたは何をしたいかという点で、この新しいリストタイプとカスタムMEFエクスポート情報の両方を利用できます。私たちは始めましょう最初の場所は、私たちの基本パイプラインのプラグインの契約です:
私は私がする必要がある場合、私はいくつかの基本共有ロジックを導入することができますので、既存のプラグインを壊すことなく、それを同行する抽象クラスを追加することを好む
public interface IPipelinePlugin
{
void Process(PipelineContext context);
}
public abstract class PipelinePluginBase : IPipelinePlugin
{
public virtual void Process(PipelineContext context)
{
}
}
。私たちは、やるメタデータ契約を定義し、カスタムエクスポート属性ます
次の事:カスタムエクスポート属性を持つ
public interface IPipelinePluginMetadata
{
string Name { get; }
string[] Dependencies { get; }
string[] Pipelines { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)]
public class PipelineAttribute : ExportAttribute, IPipelinePluginMetadata
{
public PipelineAttribute(string name)
: base(typeof(IPipelinePlugin))
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("A pipeline plugin requires a name.", "name");
Name = name;
}
public string Name { get; private set; }
public string[] Dependencies { get; set; }
public string[] Pipelines { get; set; }
}
は、私は彼らがしていることを確認するために私の輸出の形状を定義することができますすべて正しい情報をエクスポートします。
次に、カスタムプラグインを見てみましょう。、最初の単純なプラグインをのは、我々は、入力されたテキストにBBコードの装飾を適用するためのパイプラインを作成したいと仮定しましょう、そう:
[Pipeline("ApplyColour", Pipelines = new[] { "bbcode" })]
public class ApplyColourPipelinePlugin : PipelinePluginBase
{
public override void Process(PipelineContext context)
{
context.Content = "[color=f00]" + context.Content + "[/color]";
}
}
上記の例では、単に[color]
タグ内の入力テキストをラップします。 Pipeline
属性では、プラグイン名(ApplyColour
)と、この場合はbbcode
というプラグインにアクセスできるパイプラインを示します。ここでは、より複雑な例である:上記の例で
[Pipeline("MakeBold", Pipelines = new[] { "bbcode" })]
public class MakeBoldPipelinePlugin : PipelinePluginBase
{
public override void Process(PipelineContext context)
{
context.Content = "[b]" + context.Content + "[/b]";
}
}
[Pipeline("MakeItalic", Dependencies = new[] { "MakeBold" }, Pipelines = new[] { "bbcode" })]
public class MakeItalicAfterBoldPipelinePlugin : PipelinePluginBase
{
public override void Process(PipelineContext context)
{
context.Content = "[i]" + context.Content + "[/i]";
}
}
、私は2つの追加プラグイン、テキストを太字になり、その上イタリック体である1を詳述しています。 しかし、私は依存関係の要件を導入しており、MakeItalic
はMakeBold
に依存していることを私たちのプラグインシステムに語っています。
[Export]
public class PipelineManager
{
[ImportMany]
public IEnumerable<Lazy<IPipelinePlugin, IPipelinePluginMetadata>> Plugins { get; set; }
public Queue<IPipelinePlugin> BuildPipeline(string name)
{
// Get the plugins.
var plugins = Plugins
.Where(p => p.Metadata.Pipelines == null || p.Metadata.Pipelines.Contains(name)).ToList();
// Create our dependency list.
var dependencyList = new DependencyList<Lazy<IPipelinePlugin, IPipelinePluginMetadata>, string>(
l => l.Metadata.Name,
l => l.Metadata.Dependencies);
// Add each available plugin to the list.
plugins.ForEach(dependencyList.Add);
// Create our pipeline.
var pipeline = new Queue<IPipelinePlugin>();
// Now, when we enumerate over it, it will be sorted.
dependencyList.ForEach(p => pipeline.Enqueue(p.Value));
return pipeline;
}
}
当社PipelineManager
タイプがMEFによって供給され、それ[Import]
ます(IPipelinePluginMetadata
として突出可能に形作られるべき)その関連するメタデータと一緒にIPipelinePlugin
インスタンスのシリーズ:これは私たちが一緒にそれを置く方法です。このことを念頭に置いて、ここでは使用されている:
class Program
{
static void Main(string[] args)
{
var container = new CompositionContainer(new AssemblyCatalog(typeof(Program).Assembly));
var manager = container.GetExportedValue<PipelineManager>();
var pipeline = manager.BuildPipeline("bbcode");
var context = new PipelineContext("Hello World");
foreach (var plugin in pipeline)
plugin.Process(context);
Console.Write(context.Content);
Console.ReadKey();
}
}
本当に依存リスト、およびあなたのパイプライン設計は見て2つの別々の領域ですが、私は、これはあなたにどのようでし利用のアイデアを与える願っていますそれ。
私はこれをGist(https://gist.github.com/1752325)として投げました。
私はまだ依存関係が必要なときに構成されるので、私はmefの問題を見ることができません。あなたはエラーに遭遇するところで何かを試しましたか? – blindmeis
問題はmefではなく、構成がうまく機能します。問題は、すべてのプラグインインスタンスを作成した後、それらを呼び出す方法です。上記の関係は、これらのプラグインを順番に呼び出すように頼んでいますが、解決しようとしているのは、これらのプラグインをテキストエディタだけでなく、Web要求パイプラインなどの汎用的な方法で並べることです。 Matthewの答えと同じように、彼はエクスポートされたマテリアルにプラグイン名を使用し、それに応じて依存関係を作成します。これは解決できるかもしれませんが、私はまだより一般的な解決策を見いだしています。 –