C# 如何使用SimpleInjector获取特定命名空间的实例?
在解析实例时,我需要属于特定命名空间的处理程序 例如,下面的代码应该返回CompositeMessageHandler,只包含Context1Namespace中的处理程序C# 如何使用SimpleInjector获取特定命名空间的实例?,c#,dependency-injection,simple-injector,C#,Dependency Injection,Simple Injector,在解析实例时,我需要属于特定命名空间的处理程序 例如,下面的代码应该返回CompositeMessageHandler,只包含Context1Namespace中的处理程序 Context1Namesapce Handler1.cs Handler2.cs Handler3.cs Context2Namesapce Handler1.cs Handler2.cs CompositeMessageHandler.cs Type handlerType=typeof(IMess
Context1Namesapce
Handler1.cs
Handler2.cs
Handler3.cs
Context2Namesapce
Handler1.cs
Handler2.cs
CompositeMessageHandler.cs
Type handlerType=typeof(IMessageHandler).MakeGenericType(message.GetType());
动态处理程序=_container.GetInstance(handlerType,“Context1Namespace”);
如何使用simpleinjector实现此逻辑
替代解决方案:
我可以在GetInsance调用后过滤已解析的实例,但我在CompositeMessageHandler顶部有多个装饰程序处理程序,因此此解决方案会导致问题。我可以想到两种解决方案,它们在您的场景中都能起作用。您可以手动创建
InstanceProducer
实例并对其进行筛选,以获得要执行的适当处理程序,也可以利用一些环境值并应用一个装饰器,以决定是否执行此类处理程序。以下是两者的示例:
手动创建InstanceProducers:
//注册期间
var handlerProducerInfos=(
来自container.getTypeStoreRegister中的类型(typeof(IMessageHandler),程序集)
let registration=Lifestyle.Transient.CreateRegistration(类型,容器)
来自类型为.GetClosedInterfacesFor的服务(类型为(IMessageHandler))
let producer=new InstanceProducer(服务、注册)
选择新的
{
生产者=新实例生产者(服务、注册),
Namespace=type.Namespace
})
.ToArray();
//行刑期间
Type handlerType=typeof(IMessageHandler).MakeGenericType(message.GetType());
变量处理程序=
来自handlerProducerInfos中的信息
其中handlerType==info.Producer.ServiceType
其中info.Namespace==“Context1Namespace”
选择info.Producer.GetInstance();
foreach(处理程序中的动态处理程序){
}
使用环境值和特殊装饰器:
在这里,我们可以像往常一样使用CompositeMessageHandler
:
Type handlerType = typeof(IMessageHandler<>).MakeGenericType(message.GetType());
dynamic handler = _container.GetInstance(handlerType,"Context1Namespace");
我们可以按以下方式注册所有内容:
public class ContextualMessageHandlerDecorator<T> : IMessageHandler<T> {
private readonly DecoratorContext context;
private readonly IMessageHandler<T> decoratee;
public ContextualMessageHandlerDecorator(DecoratorContext context,
IMessageHandler<T> decoratee) {
this.context = context;
this.decoratee = decoratee;
}
public static string ContextNamespace { get; set; }
public void Handle(T message) {
// Here we get the ambient value from the ContextHelper and match it
// with the namespace of the real message handler
if (ContextHelper.ContextNamespace.Value.Equals(
this.context.ImplementationType.Namespace)) {
this.decoratee.Handle(message);
}
}
}
public static ContextHelper {
public static readonly ThreadLocal<string> ContextNamespace =new ThreadLocal<string>();
}
//将具体的消息处理程序注册为集合
container.RegisterCollection(typeof(IMessageHandler),程序集);
//注册组合以包装真正的消息处理程序
Register(typeof(IMessageHandler),typeof(CompositeMessageHandler));
//在此处注册您的装饰师:
//最后注册我们的“上下文”装饰器,但防止它被包装
//围绕CompositeMessageHandler。
容器.RegisterDecorator(类型为(IMessageHandler),
类型(上下文消息句柄装饰器),
c=>!c.ImplementationType.Name.StartWith(“CompositeMessageHandler”);
执行期间:
// Register the concrete message handlers as collection
container.RegisterCollection(typeof(IMessageHandler<>), assemblies);
// Register the composite to wrap the real message handlers
container.Register(typeof(IMessageHandler<>), typeof(CompositeMessageHandler<>));
// Register your decorators here:
// Register our 'contextual' decorator last, but prevent it to be wrapped
// around the CompositeMessageHandler.
container.RegisterDecorator(typeof(IMessageHandler<>),
typeof(ContextualMessageHandlerDecorator<>),
c => !c.ImplementationType.Name.StartsWith("CompositeMessageHandler"));
Type handlerType=typeof(IMessageHandler).MakeGenericType(message.GetType());
//解析复合处理程序,包装T的所有处理程序。
动态处理程序=_container.GetInstance(handlerType);
//将上下文设置为允许对命名空间进行筛选
ContextHelper.ContextNamespace.Value=“Context1Namespace”;
//处理消息
handler.Handle((动态)消息);
我可以想到两种解决方案,它们适用于您的场景。您可以手动创建InstanceProducer
实例并对其进行筛选,以获得要执行的适当处理程序,也可以利用一些环境值并应用一个装饰器,以决定是否执行此类处理程序。以下是两者的示例:
手动创建InstanceProducers:
//注册期间
var handlerProducerInfos=(
来自container.getTypeStoreRegister中的类型(typeof(IMessageHandler),程序集)
let registration=Lifestyle.Transient.CreateRegistration(类型,容器)
来自类型为.GetClosedInterfacesFor的服务(类型为(IMessageHandler))
let producer=new InstanceProducer(服务、注册)
选择新的
{
生产者=新实例生产者(服务、注册),
Namespace=type.Namespace
})
.ToArray();
//行刑期间
Type handlerType=typeof(IMessageHandler).MakeGenericType(message.GetType());
变量处理程序=
来自handlerProducerInfos中的信息
其中handlerType==info.Producer.ServiceType
其中info.Namespace==“Context1Namespace”
选择info.Producer.GetInstance();
foreach(处理程序中的动态处理程序){
}
使用环境值和特殊装饰器:
在这里,我们可以像往常一样使用CompositeMessageHandler
:
Type handlerType = typeof(IMessageHandler<>).MakeGenericType(message.GetType());
dynamic handler = _container.GetInstance(handlerType,"Context1Namespace");
我们可以按以下方式注册所有内容:
public class ContextualMessageHandlerDecorator<T> : IMessageHandler<T> {
private readonly DecoratorContext context;
private readonly IMessageHandler<T> decoratee;
public ContextualMessageHandlerDecorator(DecoratorContext context,
IMessageHandler<T> decoratee) {
this.context = context;
this.decoratee = decoratee;
}
public static string ContextNamespace { get; set; }
public void Handle(T message) {
// Here we get the ambient value from the ContextHelper and match it
// with the namespace of the real message handler
if (ContextHelper.ContextNamespace.Value.Equals(
this.context.ImplementationType.Namespace)) {
this.decoratee.Handle(message);
}
}
}
public static ContextHelper {
public static readonly ThreadLocal<string> ContextNamespace =new ThreadLocal<string>();
}
//将具体的消息处理程序注册为集合
container.RegisterCollection(typeof(IMessageHandler),程序集);
//注册组合以包装真正的消息处理程序
Register(typeof(IMessageHandler),typeof(CompositeMessageHandler));
//在此处注册您的装饰师:
//最后注册我们的“上下文”装饰器,但防止它被包装
//围绕CompositeMessageHandler。
容器.RegisterDecorator(类型为(IMessageHandler),
类型(上下文消息句柄装饰器),
c=>!c.ImplementationType.Name.StartWith(“CompositeMessageHandler”);
执行期间:
// Register the concrete message handlers as collection
container.RegisterCollection(typeof(IMessageHandler<>), assemblies);
// Register the composite to wrap the real message handlers
container.Register(typeof(IMessageHandler<>), typeof(CompositeMessageHandler<>));
// Register your decorators here:
// Register our 'contextual' decorator last, but prevent it to be wrapped
// around the CompositeMessageHandler.
container.RegisterDecorator(typeof(IMessageHandler<>),
typeof(ContextualMessageHandlerDecorator<>),
c => !c.ImplementationType.Name.StartsWith("CompositeMessageHandler"));
Type handlerType=typeof(IMessageHandler).MakeGenericType(message.GetType());
//解析复合处理程序,包装T的所有处理程序。
动态处理程序=_container.GetInstance(handlerType);
//将上下文设置为允许对命名空间进行筛选
ContextHelper.ContextNamespace.Value=“Context1Namespace”;
//处理消息
handler.Handle((动态)消息);
为什么要基于命名空间进行筛选?每个命名空间有不同的工作线程。workers从队列中弹出消息并执行处理程序,因此每个worker应该只执行自己的处理程序。在这种情况下,我仍然觉得命名空间要求很奇怪。每个处理程序通常都应该是自治的,并且有自己的队列,因此它可以失败并独立于所有其他处理程序重试。命名空间不应