统一框架DependencyAttribute只适用于公共属性?适用于、框架、属性、DependencyAttribute

2023-09-04 01:11:49 作者:掌声留给社会人

我试图清理一些前往的东西在我的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 :)