怎么办开放式泛型装饰与团结+ UnityAutoRegistration链接 [英] How to do open generic decorator chaining with unity + UnityAutoRegistration
问题描述
今天一个有趣的切线去了阅读本文就命令处理程序后,装修。我想看看我是否能实现使用统一而不是 SimpleInjector 的模式,到目前为止,它被证明是非常困难的。
Went off on an interesting tangent today after reading this article on command handler decoration. I wanted to see if I could implement the pattern using Unity instead of SimpleInjector, and so far it is proving extremely difficult.
首先我必须做的是安装 UnityAutoRegistration ,以解决开放式泛型 ICommandHandler< TCommand>
接口。对于这方面目前的解决方案如下:
The first thing I had to do was install UnityAutoRegistration to resolve the open generic ICommandHandler<TCommand>
interface. Current solution for that aspect is as follows:
Container = new UnityContainer().LoadConfiguration();
Container.ConfigureAutoRegistration()
.ExcludeSystemAssemblies()
.Include(type => type.ImplementsOpenGeneric(typeof(ICommandHandler<>)),
(t, c) => c.RegisterType(typeof(ICommandHandler<>), t)
)
.ApplyAutoRegistration()
;
本作品为第一部分,解决任何单 ICommandHandler&LT; TCommand&GT;
。什么是令人沮丧的证明迄今实施装饰处理。当我添加第二个 ICommandHandler&LT; TCommand&GT;
作为装饰,统一抛出一个StackOverflowException。我不知道有足够的了解团结内部,但我猜这是因为它不能找出解决这些实例 - 命令处理程序,或命令处理程序装饰 - 因为这两个实施 ICommandHandler&LT; TCommand&GT;
接口
This works for the first part, resolving any single ICommandHandler<TCommand>
. What's proven frustrating so far is implementing a decoration handler. As soon as I add a second ICommandHandler<TCommand>
as a decorator, Unity throws a StackOverflowException. I don't know enough about Unity internals, but I'm guessing this is because it can't figure out which instance to resolve to -- the command handler, or the command handler decorator -- since both implement the ICommandHandler<TCommand>
interface.
周围的Googling导致我<一个href="http://www.pnpguidance.net/post/GenericDecoratorChainsExampleUnityDependencyInjectionContainer.aspx"相对=nofollow>首先这篇文章,这也解释了如何做到这一点的我会考虑一个强制的方法。我还发现<一href="http://davidhayden.com/blog/dave/archive/2008/11/19/ChainResponsibilityDesignPatternUnityDependencyInjectionContainer.aspx"相对=nofollow>这些 <一个href="https://stackoverflow.com/questions/6109646/how-do-i-use-the-decorator-pattern-with-unity-without-explicitly-specifying-ever">related 页面但都不是一个完整的解决我的问题(和我太无知的数字出来为自己)。
Googling around led me first to this article, which explains how to do it in what I would consider a brute force method. I also found these related pages but none is a complete solution to my problem (and I am too ignorant to figure it out for myself).
我后来发现这篇文章中,这似乎解决我同样的问题的。但结实的解决方案并没有考虑处理开放的仿制药。目前我国大部分依赖的是从config文件的统一体部分加载,所以我不想写一吨的编译code每个处理或装饰。好像有某种UnityContainerExtension和DecoratorBuildStrategy是正确的路要走,但我不能弄明白。我一直在玩健壮的code一小会儿,现在,我完全被卡住。我试图修改他的code占仿制药,导致BadImageFormatExceptions(试图用不正确的格式加载程序(从HRESULT异常:0x8007000B))
I then found this article, which seems to address my same concerns. However beefy's solution does not account for dealing with open generics. Currently most of our dependencies are loaded from a unity section in the .config file, so I don't want to write a ton of compiled code for each handler or decorator. It seems like having some kind of UnityContainerExtension and DecoratorBuildStrategy is the right way to go, but I can't figure it out. I have been playing with beefy's code for a little while now, and am completely stuck. My attempts to modify his code to account for generics has led to BadImageFormatExceptions (An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)).
我喜欢这样做是为了贯彻落实装饰链的想法,因为它的短,只有1号线每担忧:
I like the idea of doing this to implement the decorator chaining, because it's short, and there is only 1 line per concern:
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我的容器,以简单的注射,如果我没有。
...but I don't want to change my container from Unity to Simple Injector if I don't have to.
所以我的问题是我怎么可能去实现开放一般装饰用的统一链(加上 UnityAutoRegistration
)?
SO my question is how could I go about implementing open generic decorator chaining using unity (plus UnityAutoRegistration
)?
推荐答案
这将是等值的统一:
// 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")));
这篇关于怎么办开放式泛型装饰与团结+ UnityAutoRegistration链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!