关于Castle.Windsor中实现属性类注解自动注入的说明

Castle是.NET平台上的一个开源项目,为企业级开发和WEB应用程序开发提供完整的服务。Windsor是Castle下的一个项目,用于提供IOC的解决方案。IOC被称为控制反转或者依赖注入(Inversion of Control)
以下介绍如何通过Castle.Windsor实现对类的成员属性或字段进行自动注入:

一、自动注入核心代码:

using Castle.Core;
using Castle.Core.Resource;
using Castle.MicroKernel;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using System;
using System.Collections.Generic;
using System.Reflection;

// 成员注解自动注入属性类,可注解字段和属性
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class InstanceAttribute : Attribute
{
    // 获取或设置需要注入对象的ID值
    public string ID
    {
        get;
        set;
    }

    // 获取或设置需要注入对象的类型
    public Type Type
    {
        get;
        set;
    }
}

// 成员注解自动注入功能类,继承Castle.Windsor的WindsorContainer
public class InstanceProvider : WindsorContainer
{
    // 定义Castle.Windsor在程序配置文件中的节点
    private static readonly string ConfigRoot = "windsor";
    // 定义类的成员注解信息字典
    private static Dictionary<Type, Dictionary<MemberInfo, InstanceAttribute>> _InstanceMembers = new Dictionary<Type, Dictionary<MemberInfo, InstanceAttribute>>();

    // 构造函数初始化程序默认配置文件的Castle.Windsor配置信息(也可以指定其他配置文件)
    public InstanceProvider()
      : base(new XmlInterpreter(new ConfigResource(InstanceProvider.ConfigRoot)))
    {
        // 绑定IoC组件创建事件
        this.Kernel.ComponentCreated += this.Kernel_ComponentCreated;
    }

    // 获取类型的成员注解信息
    private Dictionary<MemberInfo, InstanceAttribute> GetInstanceMembers(Type type)
    {
        // 定义类型的成员注解信息
        Dictionary<MemberInfo, InstanceAttribute> instanceMembers;
        // 获取Castle.Windsor的IoC接口
        IKernel kernel = this.Kernel;
        // 线程安全锁,防止多线程对成员注解信息字典操作的冲突
        lock (InstanceProvider._InstanceMembers)
        {
            // 判断当前类型是否已存在成员注解信息
            if (InstanceProvider._InstanceMembers.ContainsKey(type))
            {
                // 根据类型获取所属的成员注解信息
                instanceMembers = InstanceProvider._InstanceMembers[type];
            }
            else
            {
                // 新建成员注解信息
                instanceMembers = new Dictionary<MemberInfo, InstanceAttribute>();
                // 获取成员注解的属性类类型
                Type instanceAttributeType = typeof(InstanceAttribute);
                // 获取类型的成员信息
                MemberInfo[] memberInfos = type.GetMembers();
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    switch (memberInfo.MemberType)
                    {
                        case MemberTypes.Field:
                            // 获取字段成员
                            FieldInfo fieldInfo = memberInfo as FieldInfo;
                            // 获取成员注解对象
                            object[] fieldInstanceAttributes = memberInfo.GetCustomAttributes(instanceAttributeType, false);
                            // 查找有效的字段注解信息
                            foreach (InstanceAttribute instanceAttribute in fieldInstanceAttributes)
                            {
                                // 判断是否设置了需要注入对象的ID值
                                if (instanceAttribute.ID == null)
                                {
                                    // 定义IoC组件类型
                                    Type componentType;
                                    // 判断是否设置了需要注入对象的类型
                                    if (instanceAttribute.Type == null)
                                    {
                                        // 没有设置需要注入对象的类型则使用字段类型
                                        componentType = fieldInfo.FieldType;
                                    }
                                    else
                                    {
                                        // 设置IoC组件类型
                                        componentType = instanceAttribute.Type;
                                    }
                                    // 没有设置需要注入对象的ID值则根据组件类型判断是否存在对应的IoC组件
                                    if (kernel.HasComponent(componentType))
                                    {
                                        // 添加成员注解信息项
                                        instanceMembers.Add(memberInfo, instanceAttribute);
                                        break;
                                    }
                                }
                                else
                                {
                                    // 根据注入对象的ID值判断是否存在Ioc组件
                                    if (kernel.HasComponent(instanceAttribute.ID))
                                    {
                                        // 添加成员注解信息项
                                        instanceMembers.Add(memberInfo, instanceAttribute);
                                        break;
                                    }
                                }
                            }
                            break;
                        case MemberTypes.Property:
                            // 获取属性成员
                            PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                            // 判断属性成员是否可读写,并且Get、Set访问器的静态性是否一致
                            MethodInfo getMethodInfo = propertyInfo.GetGetMethodInfo();
                            MethodInfo setMethodInfo = propertyInfo.GetSetMethodInfo();
                            if (getMethodInfo != null && setMethodInfo != null && getMethodInfo.IsStatic == setMethodInfo.IsStatic)
                            {
                                // 获取属性注解对象
                                object[] propertyInstanceAttributes = memberInfo.GetCustomAttributes(instanceAttributeType, false);
                                // 查找有效的属性注解信息
                                foreach (InstanceAttribute instanceAttribute in propertyInstanceAttributes)
                                {
                                    // 判断是否设置了需要注入对象的ID值
                                    if (instanceAttribute.ID == null)
                                    {
                                        // 定义IoC组件类型
                                        Type componentType;
                                        // 判断是否设置了需要注入对象的类型
                                        if (instanceAttribute.Type == null)
                                        {
                                            // 没有设置需要注入对象的类型则使用属性类型
                                            componentType = propertyInfo.PropertyType;
                                        }
                                        else
                                        {
                                            // 设置IoC组件类型
                                            componentType = instanceAttribute.Type;
                                        }
                                        // 没有设置需要注入对象的ID值则根据组件类型判断是否存在对应的IoC组件
                                        if (kernel.HasComponent(componentType))
                                        {
                                            // 添加属性注解信息项
                                            instanceMembers.Add(memberInfo, instanceAttribute);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        // 根据注入对象的ID值判断是否存在Ioc组件
                                        if (kernel.HasComponent(instanceAttribute.ID))
                                        {
                                            // 添加属性注解信息项
                                            instanceMembers.Add(memberInfo, instanceAttribute);
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
                // 将获取到的成员注解信息保存到成员注解信息字典以备下次获取
                InstanceProvider._InstanceMembers.Add(type, instanceMembers);
            }
        }
        // 返回成员注解信息
        return instanceMembers;
    }

    // 为对象进行属性注入,静态类可通过传入Type对象进行注入
    public void Instance(object obj)
    {
        // 获取需要注入对象的类型
        Type type;
        // 判断对象是否是Type对象
        if (obj is Type)
        {
            // 直接强制转换为Type对象
            type = obj as Type;
        }
        else
        {
            // 获取对象的类型
            type = obj.GetType();
        }
        // 获取对象的成员注入信息
        Dictionary<MemberInfo, InstanceAttribute> instanceMembers = this.GetInstanceMembers(type);
        // 获取Castle.Windsor的IoC接口
        IKernel kernel = this.Kernel;
        // 开始进行成员注入
        foreach (KeyValuePair<MemberInfo, InstanceAttribute> item in instanceMembers)
        {
            switch (item.Key.MemberType)
            {
                case MemberTypes.Field:
                    // 获取字段注入信息
                    FieldInfo fieldInfo = item.Key as FieldInfo;
                    // 定义字段反射对象
                    object field;
                    // 根据字段是否是静态字段设置反射对象
                    if (fieldInfo.IsStatic)
                    {
                        field = null;
                    }
                    else
                    {
                        field = obj;
                    }
                    // 判断字段是否已经被赋值,只对未赋值字段进行注入
                    if (fieldInfo.GetValue(field) == null)
                    {
                        // 定义IoC组件类型
                        Type componentType;
                        // 判断是否设置了需要注入对象的类型
                        if (item.Value.Type == null)
                        {
                            // 没有设置需要注入对象的类型则使用字段类型
                            componentType = fieldInfo.FieldType;
                        }
                        else
                        {
                            // 设置IoC组件类型
                            componentType = item.Value.Type;
                        }
                        // 定义需要注入的字段值
                        object value;
                        // 判断是否设置了需要注入对象的ID值
                        if (item.Value.ID == null)
                        {
                            // 没有设置需要注入对象的ID值则根据类型获取对应的IoC组件
                            value = kernel.Resolve(componentType);
                        }
                        else
                        {
                            // 根据注入对象的ID值获取Ioc组件
                            value = kernel.Resolve(item.Value.ID, componentType);
                        }
                        // 通过反射为字段进行赋值
                        fieldInfo.SetValue(field, value);
                    }
                    break;
                case MemberTypes.Property:
                    // 获取属性注入信息
                    PropertyInfo propertyInfo = item.Key as PropertyInfo;
                    // 定义属性反射对象
                    object property;
                    // 根据属性是否是静态属性设置反射对象
                    MethodInfo getMethodInfo = propertyInfo.GetGetMethod();
                    MethodInfo setMethodInfo = propertyInfo.GetSetMethod();
                    if (getMethodInfo.IsStatic && setMethodInfo.IsStatic)
                    {
                        property = null;
                    }
                    else
                    {
                        property = obj;
                    }
                    // 判断属性是否已经被赋值,只对未赋值属性进行注入
                    if (propertyInfo.GetValue(property, null) == null)
                    {
                        // 定义IoC组件类型
                        Type componentType;
                        // 判断是否设置了需要注入对象的类型
                        if (item.Value.Type == null)
                        {
                            // 没有设置需要注入对象的类型则使用属性类型
                            componentType = propertyInfo.PropertyType;
                        }
                        else
                        {
                            // 设置IoC组件类型
                            componentType = item.Value.Type;
                        }
                        // 定义需要注入的属性值
                        object value;
                        // 判断是否设置了需要注入对象的ID值
                        if (item.Value.ID == null)
                        {
                            // 没有设置需要注入对象的ID值则根据类型获取对应的IoC组件
                            value = kernel.Resolve(componentType);
                        }
                        else
                        {
                            // 根据注入对象的ID值获取Ioc组件
                            value = kernel.Resolve(item.Value.ID, componentType);
                        }
                        // 通过反射为属性进行赋值
                        propertyInfo.SetValue(property, value, null);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    // 订阅IoC组件创建事件
    private void Kernel_ComponentCreated(ComponentModel model, object instance)
    {
        // 在每次创建IoC组件时进行成员注入
        this.Instance(instance);
    }
}

二、调用说明:
定义类,并对需要进行注入的属性或字段标记InstanceAttribute注解属性类。创建InstanceProvider对象,通过调用Instance方法将传入的类实例对象进行属性或字段的注入。如果是静态类可通过传入其Type对象进行注入。

更多信息请参阅:Windsor | Castle Project

发布者

陆 煜涛

http://luyutao.com/

发表评论

电子邮件地址不会被公开。 必填项已用*标注