我试图清理一些前往的东西在我的code,并在不经意间打破了统一的依赖注入。过了一会儿,我意识到,我打上一些公共属性,我真的不希望我的DLL暴露在外内部。然后,我开始变得异常。
I was trying to clean up some accessability stuff in my code, and inadvertently broke Unity dependency injection. After a while I realized that I marked some public properties that I didn't really want exposed outside my DLLs to internal. Then I started getting exceptions.
如此看来,使用统一的[依赖]属性只适用于公共属性。我想这是有道理的,因为内部和私人道具不会是可见的统一组装,但是的感觉真脏的有一大堆,你的的公共属性永远的想要的任何人设置或能够设置以外统一
So it seems that using the [Dependency] attribute in Unity only works for public properties. I suppose that makes sense since the internal and private props wouldnt be visible to the Unity assembly, but feels really dirty to have a bunch of public properties that you never want anyone to set or be able to set, other than Unity.
有没有办法让统一设置内部或私有财产吗?
Is there a way to let unity set internal or private properties too?
下面是单元测试,我想看看通。目前,只有公共道具测试通过:
Here is the unit test I'd like to see pass. Currently only the public prop test passes:
[TestFixture]
public class UnityFixture
{
[Test]
public void UnityCanSetPublicDependency()
{
UnityContainer container = new UnityContainer();
container.RegisterType<HasPublicDep, HasPublicDep>();
container.RegisterType<TheDep, TheDep>();
var i = container.Resolve<HasPublicDep>();
Assert.IsNotNull(i);
Assert.IsNotNull(i.dep);
}
[Test]
public void UnityCanSetInternalDependency()
{
UnityContainer container = new UnityContainer();
container.RegisterType<HasInternalDep, HasInternalDep>();
container.RegisterType<TheDep, TheDep>();
var i = container.Resolve<HasInternalDep>();
Assert.IsNotNull(i);
Assert.IsNotNull(i.dep);
}
[Test]
public void UnityCanSetPrivateDependency()
{
UnityContainer container = new UnityContainer();
container.RegisterType<HasPrivateDep, HasPrivateDep>();
container.RegisterType<TheDep, TheDep>();
var i = container.Resolve<HasPrivateDep>();
Assert.IsNotNull(i);
Assert.IsNotNull(i.depExposed);
}
}
public class HasPublicDep
{
[Dependency]
public TheDep dep { get; set; }
}
public class HasInternalDep
{
[Dependency]
internal TheDep dep { get; set; }
}
public class HasPrivateDep
{
[Dependency]
private TheDep dep { get; set; }
public TheDep depExposed
{
get { return this.dep; }
}
}
public class TheDep
{
}
更新:
我注意到调用栈设置从传递的属性:
I noticed the call stack to set the property passed from:
UnityCanSetPublicDependency()
--> Microsoft.Practices.Unity.dll
--> Microsoft.Practices.ObjectBuilder2.dll
--> HasPublicDep.TheDep.set()
所以,企图至少使内部版本的工作,我说这些我组装的特性:
So in an attempt to at least make the internal version work, I added these to my assembly's properties:
[assembly: InternalsVisibleTo("Microsoft.Practices.Unity")]
[assembly: InternalsVisibleTo("Microsoft.Practices.Unity.Configuration")]
[assembly: InternalsVisibleTo("Microsoft.Practices.ObjectBuilder2")]
但是,没有任何变化。团结/ ObjectBuilder的仍然不会设置内部属性
However, no change. Unity/ObjectBuilder still won't set the internal property
推荐答案
在反射周围戳一个LOF后嘛,我想通了这一点。 默认情况下,code,发现一个构造函数构造函数注入呼叫:
Well after a lof of poking around in reflector, I figured this out. By default, the code that finds a constructor for constructor injection calls:
ConstructorInfo[] constructors = typeToConstruct.GetConstructors()
如果没有的BindingFlags,这将只检测公共构造。 对于一些挂羊头卖狗肉(从反射镜如复制/粘贴),你可以做一个UnityContainerExtension做所有同样的东西作为默认的实现,但改变调用GetConstructors()为:
With no BindingFlags, that will only detect public constructors. With some trickery (as in copy/paste from reflector) you can make a UnityContainerExtension that does all the same stuff as the default implementation, but change the call to GetConstructors() to:
ConstructorInfo[] constructors = typeToConstruct..GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
然后添加扩展到统一容器。该实施extenstion是〜100线$ C $ C,所以我在这里不糊。如果有人想它,让我知道...
Then add the extension into the unity container. The implemented extenstion is ~100 lines of code, so I didn't paste it here. If anyone wants it, let me know...
新的工作测试用例。请注意,所有的统一创建的类现在内部的:
New working test case. Note that all the Unity created classes are now internal:
[TestFixture]
public class UnityFixture
{
[Test]
public void UnityCanSetInternalDependency()
{
UnityContainer container = new UnityContainer();
container.AddNewExtension<InternalConstructorInjectionExtension>();
container.RegisterType<HasInternalDep, HasInternalDep>();
container.RegisterType<TheDep, TheDep>();
var i = container.Resolve<HasInternalDep>();
Assert.IsNotNull(i);
Assert.IsNotNull(i.dep);
}
}
internal class HasInternalDep
{
internal HasInternalDep(TheDep dep)
{
this.dep = dep;
}
internal TheDep dep { get; set; }
}
internal class TheDep
{
}
我敢肯定,我可以提出延期做同样的解决非公共属性,但code是一个复杂多了:)
I'm sure I can make an extension to do the same to resolve non-public properties, but that code was a lot more complicated :)
相关推荐
最新文章