我將從具有約100個註冊組件(大多數是單件)的現有項目的Windsor切換到結構映射。 所有組件都從提供日誌記錄和運行狀況跟蹤的公共基類繼承,因此包含用於標識組件實例的「Name」屬性。將註冊名稱綁定到結構映射中的組件實例
藉助Windsor,可以將組件的Name屬性設置爲用於在IOC容器中註冊組件的名稱(我們爲此使用了一個Facility)。
我的問題:這是可能的結構圖嗎?
(我夢想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
持續到達。
我的第二好辦法是定義一個新的「NamedComponent(...)」擴展方法,它解析爲Named(name).WithProperty(x => x.Name).EqualTo(name)
,但我想知道是否可以避免將組件註冊保持爲「類似於結構圖」
我錯過了什麼嗎?
是的,'EnrichWith'真的看起來比'WithProperty'好 - 好點。 我的問題的核心是'context.RequestedName'不會返回被實例化的組件的名稱,而是被請求的組件的名稱。 – streuspeicher
我想要阻止的是我必須將「豐富」添加到100多個組件註冊中,但是可能自定義擴展方法真的是這裏要走的路。謝謝! – streuspeicher
是的,從這個角度來看,我認爲擴展方法是一個很酷的解決方案 - 我可以幫助的只是實現該方法,不知道任何直接實現您的目標的東西。 – AlexCuse