gpt4 book ai didi

c# - 如何使用 unity + UnityAutoRegistration 进行开放式通用装饰器链接

转载 作者:行者123 更新时间:2023-11-30 14:15:34 24 4
gpt4 key购买 nike

今天阅读了一个有趣的切线this article on command handler decoration .我想看看我是否可以使用 Unity 而不是 SimpleInjector 来实现该模式,到目前为止,这被证明是极其困难的。

我要做的第一件事是安装 UnityAutoRegistration解决开放通用ICommandHandler<TCommand>界面。目前该方面的解决方案如下:

Container = new UnityContainer().LoadConfiguration();

Container.ConfigureAutoRegistration()
.ExcludeSystemAssemblies()
.Include(type => type.ImplementsOpenGeneric(typeof(ICommandHandler<>)),
(t, c) => c.RegisterType(typeof(ICommandHandler<>), t)
)
.ApplyAutoRegistration()
;

这适用于第一部分,解析任何单个 ICommandHandler<TCommand> .到目前为止,令人沮丧的是实现装饰处理程序。只要我添加第二个 ICommandHandler<TCommand>作为装饰器,Unity 抛出 StackOverflowException。我对 Unity 内部机制了解不够,但我猜这是因为它无法确定要解析到哪个实例——命令处理程序或命令处理程序装饰器——因为它们都实现了 ICommandHandler<TCommand>。界面。

谷歌搜索引导我 first to this article ,它解释了如何用我认为的蛮力方法来做到这一点。我还找到了these related pages但没有一个能完全解决我的问题(我太无知了,无法自己解决)。

然后我找到了this article, which seems to address my same concerns .但是,beefy 的解决方案并未考虑处理开放泛型。目前我们的大部分依赖项都是从 .config 文件中的统一部分加载的,所以我不想为每个处理程序或装饰器编写大量编译代码。似乎拥有某种 UnityContainerExtension 和 DecoratorBuildStrategy 是正确的方法,但我无法弄清楚。我已经使用 beefy 的代码玩了一段时间了,完全卡住了。我试图修改他的代码以解决泛型导致 BadImageFormatExceptions(试图加载格式不正确的程序。(HRESULT 异常:0x8007000B))。

我喜欢这样做来实现装饰器链的想法,因为它很短,而且每个关注点只有 1 行:

var container = new Container();

// Go look in all assemblies and register all implementations
// of ICommandHandler<T> by their closed interface:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());

// Decorate each returned ICommandHandler<T> object with an
// TransactionCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));

// Decorate each returned ICommandHandler<T> object with an
// DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>));

...但如果没有必要,我不想将我的容器从 Unity 更改为 Simple Injector。

所以我的问题是我如何使用 unity(加上 UnityAutoRegistration)来实现开放式通用装饰器链?

最佳答案

这在 Unity 中是等价的:

// Go look in all assemblies and register all implementa-
// tions of ICommandHandler<T> by their closed interface:
var container = new UnityContainer();

var handlerRegistrations =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from implementation in assembly.GetExportedTypes()
where !implementation.IsAbstract
where !implementation.ContainsGenericParameters
let services =
from iface in implementation.GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() ==
typeof(ICommandHandler<>)
select iface
from service in services
select new { service, implementation };

foreach (var registration in handlerRegistrations)
{
container.RegisterType(registration.service,
registration.implementation, "Inner1");
}

// Decorate each returned ICommandHandler<T> object with an
// TransactionCommandHandlerDecorator<T>.
container.RegisterType(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>),
"Inner2",
InjectionConstructor(new ResolvedParameter(
typeof(ICommandHandler<>), "Inner1")));

// Decorate each returned ICommandHandler<T> object with an
// DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterType(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>),
InjectionConstructor(new ResolvedParameter(
typeof(ICommandHandler<>), "Inner2")));

关于c# - 如何使用 unity + UnityAutoRegistration 进行开放式通用装饰器链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9813630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com