C# 如何使用SimpleInjector获取特定命名空间的实例?

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

在解析实例时,我需要属于特定命名空间的处理程序

例如,下面的代码应该返回CompositeMessageHandler,只包含Context1Namespace中的处理程序

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应该只执行自己的处理程序。在这种情况下,我仍然觉得命名空间要求很奇怪。每个处理程序通常都应该是自治的,并且有自己的队列,因此它可以失败并独立于所有其他处理程序重试。命名空间不应