内部设置器进行属性注入 [英] Property Injection with internal setter

查看:103
本文介绍了内部设置器进行属性注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an existing application that I am modifying to use Autofac Property Injection. It seems regardless of which method I use to register my types with properties, the properties are always null unless they have public setters. With other IoC containers (e.g. Structuremap) it's possible to scope the setter internal and make it available using the InternalsVisibleTo attribute on the assembly. This would seem nice to restrict clients from modifying the assignment.

Autofac可以做到吗?还是在进行属性注入以确保分配安全时使用另一种方法?

Is this possible with Autofac? Or is there another approach when working with property injection to keep the assignments secure?

我尝试将反射与PropertiesAutoWired()一起使用,并尝试从WebApi Global.asax中解析.WithParameter()-指定要成功设置的特定参数作为内部设置器.

I've tried using reflection with PropertiesAutoWired() as well as resolving .WithParameter() from my WebApi Global.asax - specifying the specific parameter to be set with no success as an internal 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
            }
        }
    }
}

推荐答案

您不能使用autofac注入internal setter,因为AutowiringPropertyInjector类仅在寻找公共属性(请参见

You cannot inject internal setters with autofac, because the AutowiringPropertyInjector class is only looking for public properties (see source).

但是AutowiringPropertyInjector中的逻辑非常简单,因此您可以创建自己的版本,该版本可以对非公共属性进行注入:

However a logic in the AutowiringPropertyInjector is very simple so you can create your own version which does injection for non public properties:

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

And now you can use this class in the OnActivated event

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

但是,上面列出的解决方案现在可以注入所有类型的属性,因此即使是私有属性也可以注入受保护的属性,因此您可能需要进行一些附加检查来扩展它,以确保仅注入所需的属性.

However the above listed solution now injects all kind of properties so even private and protected ones so you may need to extend it with some additional checks to make sure that you will only inject the properties what you would expect.

这篇关于内部设置器进行属性注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆