私は現在MEFをプロジェクトで使用していますが、従来のコンポーネントはすべてのコンポーネントをエクスポートするためにCastleを使用しています。Silverlightで城のカーネルからMEFをインポート
新しいオブジェクトを作成するときに、このカーネルからインポートすることができます。また、Xapからのエクスポートを取得することもできます。
これは可能ですか?いくつかのサンプルコードを表示できますか?
私は現在MEFをプロジェクトで使用していますが、従来のコンポーネントはすべてのコンポーネントをエクスポートするためにCastleを使用しています。Silverlightで城のカーネルからMEFをインポート
新しいオブジェクトを作成するときに、このカーネルからインポートすることができます。また、Xapからのエクスポートを取得することもできます。
これは可能ですか?いくつかのサンプルコードを表示できますか?
マシューが正しく言ったように、これはExportProvider
別の例を使用している実行する方法は、(それがXAMLからの輸出を実証)hereです。 以下は、私が最後に問題を解決するために行ったことです。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace MEFCastleBridge
{
public class CastleExportProvider : ExportProvider
{
WindsorContainer _container;
private readonly Dictionary<ExportDefinition, List<Export>> _exports =
new Dictionary<ExportDefinition, List<Export>>();
private readonly object _sync = new object();
public CastleExportProvider(WindsorContainer container)
{
_container = container;
var handlers = _container.Kernel.GetAssignableHandlers(typeof(object));
foreach (var handler in handlers)
{
RegisterCastleComponent(handler);
}
_container.Kernel.ComponentRegistered += ComponentRegistered;
}
protected override IEnumerable<Export> GetExportsCore(
ImportDefinition definition, AtomicComposition atomicComposition)
{
var contractDefinition = definition as ContractBasedImportDefinition;
var retVal = Enumerable.Empty<Export>();
if (contractDefinition != null)
{
string contractName = contractDefinition.ContractName;
if (!string.IsNullOrEmpty(contractName))
{
var exports =
from e in _exports
where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
select e.Value;
if (exports.Count() > 0)
{
retVal = exports.First();
}
}
}
return retVal;
}
void RegisterCastleComponent(IHandler handler)
{
var type = handler.Service;
var contractName = type.ToString();
lock (_sync)
{
var found = from e in _exports
where string.Compare(e.Key.ContractName,
contractName, StringComparison.OrdinalIgnoreCase) == 0
select e;
if (found.Count() == 0)
{
var metadata = new Dictionary<string, object>();
var definition = new ExportDefinition(contractName, metadata);
_exports.Add(definition, new List<Export>());
}
var wrapper = new Export(contractName,() => _container.Resolve(type));
found.First().Value.Add(wrapper);
}
}
void ComponentRegistered(string key, IHandler handler)
{
RegisterCastleComponent(handler);
}
}
public interface IMyComponent
{
string TheString { get; }
}
public class RegisteredComponent : IMyComponent
{
public string TheString { get { return "RegisteredComponent"; } }
}
[Export(typeof(IMyComponent))]
public class ExportedComponent : IMyComponent
{
public string TheString { get { return "ExportedComponent"; } }
}
public class ExportExample
{
// Will contain an instance of RegisteredComponent and ExportedComponent
[ImportMany]
public List<IMyComponent> Components { get; set; }
public ExportExample()
{
// Create a Windsor container and add a type.
var container = new WindsorContainer();
container.Register(Component.For<IMyComponent>().ImplementedBy<MyComponent>().LifeStyle.Singleton);
// Add the Export Provider, in addition to the DeploymentCatalog
var compContainer = new CompositionContainer(new DeploymentCatalog(), new CastleExportProvider(container));
// Should only be called once, before any attempt to SatisfyImports.
CompositionHost.Initialize(compContainer);
CompositionInitializer.SatisfyImports(this);
Test = string.Join(", ", Components.Select(c => c.DoSomething));
}
public string Test { get; set; }
}
}
MEFはできるだけ柔軟に設計されていますが、秘密裏に隠されていて本当に素敵な機能の1つは、新しいコンポーネントをプラグインできる新しいExportProvider
インスタンスを定義する機能です。私はこれまで、MEFプロジェクトのASP.NET MVC(パート3 hereを参照)でCommon Service Locatorプロジェクトを利用してこれについて説明しました。
CSLは、等
別の好例城、Autofac、Ninject、ユニティなどの既存のIoCコンテナの多くのために多くの特定のCSL実装が存在するようhereを見つけることができる、素敵な柔軟なアプローチでありますわずかに異なるが基本的には同様のアプローチを示す。