100個までの登録済みコンポーネント(ほとんどがシングルトン)を持つ既存のプロジェクトで、WindsorからStructuremapに切り替えようとしています。すべてのコンポーネントは、ロギングとヘルストラッキングを提供する共通の基本クラスを継承しているため、コンポーネントインスタンスを識別するために使用される「Name」プロパティが含まれています。
Windsorを使用すると、コンポーネントのNameプロパティを、コンポーネントをIOCコンテナに登録するために使用された名前に設定することができました(このためにファシリティを使用しました)。
私の質問:Structuremapでこのようなことが可能ですか?
c.For<IFoo>.Use<Bar>.Named("Doe")
(私はそれへの呼び出しが魔法のようにinstanceOfBar.Name = "Doe"
どこかに帰着することを夢見ています。)
これが私が試したことです:
using System;
using StructureMap;
using StructureMap.Interceptors;
using System.Diagnostics;
namespace ConsoleApplication1
{
interface IServiceA { }
interface IServiceB { }
class Base
{
public string Name { get; set; }
}
class ComponentA : Base, IServiceA { }
class ComponentB : Base, IServiceB
{
public ComponentB(IServiceA serviceA)
{
this.ServiceA = serviceA;
}
public IServiceA ServiceA { get; private set; }
}
class SetNameInterceptor : TypeInterceptor
{
public bool MatchesType(Type type) { return true; }
public object Process(object target, IContext context)
{
// *** Any other way? This does not work...
string name = context.BuildStack.Current != null ? context.BuildStack.Current.Name : context.RequestedName;
((Base)target).Name = name;
return target;
}
}
class Program
{
static void Main(string[] args)
{
Container container = new Container(c =>
{
c.RegisterInterceptor(new SetNameInterceptor());
c.For<IServiceA>().Use<ComponentA>().Named("A");
c.For<IServiceB>().Use<ComponentB>().Named("B");
});
var b = container.GetInstance<IServiceB>();
// both Fail:
Debug.Assert(((ComponentB)b).Name == "B");
Debug.Assert(((ComponentA)((ComponentB)b).ServiceA).Name == "A");
}
}
}
上記は明らかに機能しません。私はいくつかのバリエーションを試しましたが、運がありませんでした。ターゲットオブジェクトの登録名は、を介して一貫して到達できるようには見えませんIContext
。
私の2番目に良いアプローチは、に解決される新しい「NamedComponent(...)」拡張メソッドを定義することですNamed(name).WithProperty(x => x.Name).EqualTo(name)
が、コンポーネントの登録を「構造マップのような」ものとして維持するために、これを回避できるかどうか疑問に思います。
私は何かが足りないのですか?