gpt4 book ai didi

properties - 使用内部 setter 进行属性注入(inject)

转载 作者:行者123 更新时间:2023-12-01 11:42:32 25 4
gpt4 key购买 nike

我有一个现有的应用程序,我正在修改它以使用 Autofac 属性注入(inject)。似乎无论我使用哪种方法向属性注册我的类型,属性始终为空,除非它们具有公共(public) setter 。对于其他 IoC 容器(例如 Structuremap),可以将 setter 设置为内部范围并使用 InternalsVisibleTo 使其可用。程序集上的属性。这似乎很好地限制了客户修改分配。

Autofac可以做到这一点吗?或者在使用属性注入(inject)以确保分配安全时是否有另一种方法?

我尝试使用反射与 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
}
}
}
}

最佳答案

您不能注入(inject) internal使用 autofac 的 setter ,因为 AutowiringPropertyInjector类只寻找公共(public)属性(见 source )。

然而 AutowiringPropertyInjector 中的逻辑非常简单,因此您可以创建自己的版本,为非公共(public)属性注入(inject):

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 中使用此类事件

var builder = new ContainerBuilder();
builder.RegisterType<MyPublicClass>();
builder.RegisterType<BaseContext>()
.OnActivated(args =>
AutowiringNonPublicPropertyInjector
.InjectProperties(args.Context, args.Instance, true));

然而,上面列出的解决方案现在注入(inject)了所有类型的属性,所以即使是私有(private)的和 protected ,所以您可能需要通过一些额外的检查来扩展它,以确保您只会注入(inject)您期望的属性。

关于properties - 使用内部 setter 进行属性注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18188427/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com