我正在修改一个现有应用程序以使用 Autofac 属性注入。似乎无论我使用哪种方法向属性注册类型,属性始终为 null,除非它们具有公共设置器。对于其他 IoC 容器(例如 Structuremap),可以使用 setter 内部范围并使其可用InternalsVisibleTo
程序集上的属性。这似乎可以很好地限制客户修改作业。
Autofac 可以做到这一点吗?或者在使用属性注入时是否有另一种方法来保证分配的安全?
我尝试过使用反射PropertiesAutoWired()
以及解决.WithParameter()
来自我的 WebApi Global.asax - 指定要设置的特定参数,但作为内部设置器没有成功。
[assembly: InternalsVisibleTo("MyWebAPI.dll")]
[assembly: InternalsVisibleTo("Autofac.dll")]
[assembly: InternalsVisibleTo("Autofac.Configuration.dll")]
namespace My.Namespace
{
public class BaseContext
{
public MyPublicClass _dbHelper { get; internal set; }
public BaseContext()
{
}
protected string DbConnectionString
{
get
{
return _dbHelper.DbConn; //<-Always null unless setter is public
}
}
}
}
你不能注射internal
使用 autofac 设置器,因为AutowiringPropertyInjector
类只寻找公共属性(参见source https://code.google.com/p/autofac/source/browse/Core/Source/Autofac/Core/Activators/Reflection/AutowiringPropertyInjector.cs).
然而其中的一个逻辑AutowiringPropertyInjector
非常简单,因此您可以创建自己的版本来对非公共属性进行注入:
public static class AutowiringNonPublicPropertyInjector
{
public static void InjectProperties(IComponentContext context,
object instance, bool overrideSetValues)
{
if (context == null)
throw new ArgumentNullException("context");
if (instance == null)
throw new ArgumentNullException("instance");
foreach (
PropertyInfo propertyInfo in
//BindingFlags.NonPublic flag added for non public properties
instance.GetType().GetProperties(BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic))
{
Type propertyType = propertyInfo.PropertyType;
if ((!propertyType.IsValueType || propertyType.IsEnum) &&
(propertyInfo.GetIndexParameters().Length == 0 &&
context.IsRegistered(propertyType)))
{
//Changed to GetAccessors(true) to return non public accessors
MethodInfo[] accessors = propertyInfo.GetAccessors(true);
if ((accessors.Length != 1 ||
!(accessors[0].ReturnType != typeof (void))) &&
(overrideSetValues || accessors.Length != 2 ||
propertyInfo.GetValue(instance, null) == null))
{
object obj = context.Resolve(propertyType);
propertyInfo.SetValue(instance, obj, null);
}
}
}
}
}
现在您可以在OnActivated
event
var builder = new ContainerBuilder();
builder.RegisterType<MyPublicClass>();
builder.RegisterType<BaseContext>()
.OnActivated(args =>
AutowiringNonPublicPropertyInjector
.InjectProperties(args.Context, args.Instance, true));
然而,上面列出的解决方案现在注入了所有类型的属性,甚至是私有和受保护的属性,因此您可能需要通过一些额外的检查来扩展它,以确保您只会注入您期望的属性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)