Fra*_*att 3 properties internal autofac
我有一个现有的应用程序,我正在修改以使用Autofac Property Injection.似乎无论我使用哪种方法来注册具有属性的类型,除非它们具有公共setter,否则属性始终为null.使用其他IoC容器(例如Structuremap),可以将setter设置为内部范围,并使用InternalsVisibleTo程序集中的属性使其可用.限制客户端修改赋值似乎很好.
Autofac可以实现吗?或者在处理属性注入时是否有另一种方法来保证分配安全?
我尝试过使用反射PropertiesAutoWired()以及.WithParameter()从我的WebApi Global.asax中解析- 指定要设置的特定参数,但没有成功作为内部setter.
[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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您不能internal使用autofac 注入setter,因为AutowiringPropertyInjector该类只查找公共属性(请参阅source).
但是,这里的逻辑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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以在OnActivated活动中使用这个类了
var builder = new ContainerBuilder();
builder.RegisterType<MyPublicClass>();
builder.RegisterType<BaseContext>()
.OnActivated(args =>
AutowiringNonPublicPropertyInjector
.InjectProperties(args.Context, args.Instance, true));
Run Code Online (Sandbox Code Playgroud)
但是,上面列出的解决方案现在注入所有类型的属性,所以即使是私有属性和受保护的属性也是如此,因此您可能需要通过一些额外的检查来扩展它,以确保您只注入您期望的属性.
| 归档时间: |
|
| 查看次数: |
1993 次 |
| 最近记录: |