我即将从 Windsor 切换到 Structuremap 以用于现有项目,其中包含大约 100 个注册组件(主要是单例)。所有组件都继承自一个提供日志记录和健康跟踪的通用基类,因此,它包含一个用于标识组件实例的“名称”属性。
使用 Windsor,可以将组件的 Name 属性设置为用于在 IOC 容器中注册组件的名称(我们为此使用了 Facility)。
我的问题: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
.
我的第二个最佳方法是定义一个解析为的新“NamedComponent(...)”扩展方法Named(name).WithProperty(x => x.Name).EqualTo(name)
,但我想知道是否可以避免这种情况,以尽可能保持组件注册为“类似结构图”?
我错过了什么吗?