【发布时间】:2013-08-26 08:47:00
【问题描述】:
我有一个 Windsor 服务和两个实现它的组件: 一个是“真实”服务,一个是“代理”(作为装饰器实现),将调用路由到“真实”服务或 Web 服务。
现在理想的情况是,如果找到代理 DLL,代理将用作装饰器。 如果它不存在,所有调用都将直接转到“真实”服务。
我目前正在使用“FromAssembly.InDirectory”来注册组件,这就像一个魅力。 但是,我认为这只是因为程序集恰好以正确的字母顺序命名,因此“真实”服务在“代理”(装饰器)之前注册。 (如果我错了,请纠正我。)
这对我来说看起来不太健壮。 有没有更好的方法来做到这一点,而无需手动配置配置文件中的每个组件?
我想要一个配置文件,我只会按正确的顺序列出程序集,并且这些文件中的所有组件都会自动注册(就像 FromAssembly.Named)。
或者——那会更好——一些机制可以自动确定哪个组件是装饰器(毕竟,它依赖于它实现的服务,而“真正的”服务没有),以及哪个一个是“真正的服务”,然后按照正确的顺序自动注册。
我当然可以自己实现后一种逻辑,但我不想重新发明轮子。
任何建议都将受到高度赞赏。 谢谢!
编辑: 这就是我到目前为止所拥有的。 如何确保命名默认组件(装饰器,如果有,则为默认组件),以便 WCF 工具可以通过其名称找到它? 我的意思是,我可以在装饰器部分添加一个“命名”调用,但是如果没有定义装饰器怎么办?
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var currDomain = AppDomain.CurrentDomain;
var webAppBinDir = currDomain.RelativeSearchPath;
var assemblyDir = (!string.IsNullOrEmpty(webAppBinDir)) ? webAppBinDir : currDomain.BaseDirectory;
container.Register(
Classes.FromAssemblyInDirectory(new AssemblyFilter(assemblyDir, Mask))
.Where(ImplementsServiceContract)
.WithServiceSelect((x, y) => GetServices(x))
.ConfigureIf(IsDecorator, c => c.IsDefault(y => IsDecorating(c, y)))
);
}
private static bool ImplementsServiceContract(Type type)
{
return GetServices(type).Any();
}
private static IEnumerable<Type> GetServices(Type type)
{
return type.GetInterfaces().Where(IsServiceContract);
}
private static bool IsServiceContract(Type type)
{
var ns = type.Namespace;
return ns != null && ns.StartsWith(NamespacePrefix) && Attribute.IsDefined(type, typeof(ServiceContractAttribute));
}
private static bool IsDecorator(ComponentRegistration c)
{
Type component = c.Implementation;
return GetServices(component).Any(x => IsDecorating(c, x));
}
private static bool IsDecorating(ComponentRegistration c, Type service)
{
Type component = c.Implementation;
return service.Assembly != component.Assembly;
}
【问题讨论】:
标签: c# .net reflection castle-windsor decorator