UnityContainer 和内部构造函数
我有一个带有内部构造函数的类,想要从 Unity (2.0) 中解析它。
public class MyClass {
internal MyClass(IService service) {
}
}
然后我
_container.Resolve<MyClass>();
这样做时,我有一个异常
Exception is: InvalidOperationException - The type MyClass cannot be constructed.
IService 已注册,唯一的问题是构造函数是内部的。 我真的希望这个类是公共的,但我希望它只能通过工厂创建(我实际上在工厂中调用 container.Resolve
)。
有没有办法让 Unity 看到内部构造函数?比如InternalsVisibleTo之类的?
I have a class with internal constructor and want to Resolve it from Unity (2.0).
public class MyClass {
internal MyClass(IService service) {
}
}
then I'm doing
_container.Resolve<MyClass>();
when I do so I have an exception
Exception is: InvalidOperationException - The type MyClass cannot be constructed.
IService is registered and the only problem is that constructor is internal.
I really want this class to be public, but I want it to be creatable only via a factory (in which I'm actually calling container.Resolve<MyClass>()
).
Is there a way to make Unity see that internal constructor? Like InternalsVisibleTo or something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我深入研究了如何为此目的扩展 Unity,并发现了一些有趣的信息。
首先,Unity 似乎通过内部解析 IConstructorSelectorPolicy 来选择要使用的构造函数。 Unity 中包含公共抽象类 ConstructorSelectorPolicyBase,其中包含以下 gem:
FindInjectionConstructor
和 company 是此类中的私有静态
方法,最终最终调用Type.GetConstructors
(不带参数的重载,仅返回public
构造函数)。这告诉我,如果您可以安排 Unity 使用您自己的构造函数选择器策略,该策略将能够选择任何构造函数,那么您就是黄金。有很好的文档介绍如何制作并利用您自己的容器扩展,因此我认为很有可能制作您自己的
CustomConstructorSelectorPolicy
,其中包含DefaultUnityConstructorSelectorPolicy
(派生来自抽象基类,并且是默认值,除非您注册其他内容)和ConstructorSelectorPolicyBase
< /a> (直接从中派生可能效果不佳,因为关键方法不是虚拟
,但您可以重用该代码)。因此我想说这是可行的,有一定的麻烦,但从工程的角度来看,最终结果将是相当“纯粹的”。
I dug a little into how you might extend Unity for this purpose, and found some interesting information.
First, it seems that Unity selects which constructor to use by internally resolving an
IConstructorSelectorPolicy
. Included in Unity is thepublic abstract class ConstructorSelectorPolicyBase<TInjectionConstructorMarkerAttribute>
, which includes this gem:FindInjectionConstructor
and company areprivate static
methods in this class which ultimately end up callingType.GetConstructors
(the overload with no parameters, which only returnspublic
constructors). This tells me that if you can arrange for Unity to use your own constructor selector policy, which would be able to select any constructor, you are golden.There is good documentation about how to make and utilize your own container extensions, so I imagine it's quite possible to make your own
CustomConstructorSelectorPolicy
that includes the relevant portions ofDefaultUnityConstructorSelectorPolicy
(which derives from the abstract base class and is the default unless you register something else) andConstructorSelectorPolicyBase
(deriving from this directly would probably not work well because key methods are notvirtual
, but you can reuse the code).Therefore I 'd say it's doable with a moderate amount of hassle, but the end result would be quite "pure" from an engineering point of view.
Unity 只会查看公共构造函数,因此您需要将此构造函数设为公共。
在这种情况下,创建一个工厂:
注册:
并解析:
您还可以使用 Unity 的
InjectionFactory
:为此,保存此代码的程序集应该能够看到程序集的内部结构包含
MyClass
。换句话说,MyClass
程序集应使用InternalsVisibleTo
进行标记。还可以的方法如下:
虽然您不必将构造函数公开,但这是混淆代码的好方法:-)
Unity will only look at public constructors, so you need to make this constructor public.
In that case, create a factory:
And register:
And resolve:
You can also use Unity's
InjectionFactory
:For this to work the assembly that holds this code should be able to see the internals of the assembly that holds the
MyClass
. In other words theMyClass
assembly should be marked withInternalsVisibleTo
.What would also work is the following:
Although you won't have to make the constructor public, it is a great way to obfuscate your code :-)
只需将类内部和构造函数设为公共...
Just make the class internal and the constructor public...
可能有解决方法/黑客可以让您使用 Unity 9 执行此操作(我不知道是否有),但一般来说,如果您希望一个类由 Unity(或任何 IOC 容器)管理,则它需要是公共的与公共构造函数。
一种选择可能是创建一个抽象工厂来创建具有公共构造函数的类,并将该类的构造函数保留在内部。缺点是你的工厂将由 Unity 管理,但你的类本身不会。
It's possible there are workarounds/hacks that would allow you to do this with Unity 9I don't know if any), but in general if you want a class to be managed by Unity (or any IOC container), it needs to be public with a public constructor.
One option might be to make an abstract factory that creates the class that has a public constructor, and keep the class's constructor internal. The downside is then your factory will be managed by Unity, but your class itself will not.