最近项目里用到了利用特性和反射的方式实现解耦。下面分别来了解下什么事特性,反射,以及代码中如何实现解耦的。    
     什么是特性?特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明行标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等信息。.Net框架提供了两种类型的特性:预定义特性和自定义特性。
     包括规定特性,预定义特性,自定义特性。
     其中规定特性包括:    
     AttributeUsage描述了如何使用一个自定义特性类,它规定了特性可应用到的项目的类型; 
     Conditional标记了一个条件方法,其执行依赖于它的预处理标识符,它会一起方法调用的条件编译,取决于指定的值,比如Debug或Trace。例如,当调试代码时显示变量的值;
     Obsolete标记了不应被使用的程序实体,它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为obsolete(过时的)。(具体不再详述)   
     小编在这里主要介绍
     创建自定义特性以及利用反射查找该特性,如下:
    .Net框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。
     创建并使用自定义特性包还四个步骤:
     声明自定义特性;
     构建自定义特性;
     在目标程序元素上应用自定义特性;
  通过反射访问特性;
     最后一个步骤包含编写一个简单的程序来读取元数据以便查找各种符号。元数据是用于描述其他数据的数据和信息。改程序应使用反射来在运行时访问特性。
     1、声明自定义特性,一个特性应派生System.Attribute

    /// <summary>
    /// 业务对象的元数据标记
    /// </summary>
    public class BeanAttribute : Attribute
    {
        
    }

      2 、构建自定义特性    

 /// <summary>
    /// 业务对象的元数据标记
    /// </summary>
    public class BeanAttribute : Attribute
    {
        /// <summary>
        /// 业务对象名称
        /// </summary>
        public string BeanName { get; set; }
    }
      3、 应用自定义特性
[Bean(BeanName="bean_user_login")]
     public class LoginBean:IBean
    {
        private ILoger loger = Loger.GetInstance();
        private string _BeanName = "bean_user_login";

        public string BeanName
        {
            get
            {
               return _BeanName;
            }
            set
            {
                _BeanName=value;
            }
        }
        public void Init()
        {
           
        }       
    }
      4、通过反射访问特性
    private Dictionary<string, IBean> beanObjcetDic = new Dictionary<string, IBean>();
        /// <summary>
        /// 加载全部的业务对象
        /// </summary>
        private void LoadAllBeanObject()
        {
            try
            {
                //获取本程序集下实现IBean接口的全部业务对象实例。
                Assembly ModelBuilderAbly = Assembly.GetExecutingAssembly();

                Type[] types = ModelBuilderAbly.GetTypes();

                foreach (Type type in types)
                {
                    //如果当前类型实现了IBean接口
                    if (type.GetInterface("IBean") != null)
                    {
                       //检索应用与指定成员的指定类型的自定义特性
                        BeanAttribute theBeanAttri = type.GetCustomAttribute(typeof(BeanAttribute)) as BeanAttribute;

                        //并且定义了业务标记
                        if (theBeanAttri != null)
                        {
                            //添加到业务构造器实例字典
                            IBean beanObj = Activator.CreateInstance(type) as IBean;

                            if (beanObj != null)
                            {
                                //1.调用业务对象的初始化方法,完成初始化
                                beanObj.Init();

                                //2.将初始化完毕的业务对象,添加到业务对象字典中
                                beanObjcetDic.Add(theBeanAttri.BeanName, beanObj);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {//系统日志
              loger.WriteLog("BeanManager.LoadAllBeanObject", e, LogLevel.Error, typeof(BeanManager));
            }
        }
利用反射查看元数据
  public object Action(string actionName, params object[] actionPars)
        {
            try
            {
                if (string.IsNullOrEmpty(actionName))
                    return null;

                Type thisType = this.GetType();
                //发现方法的属性并提供对方法元数据的访问
                MethodInfo theActionMI = thisType.GetMethod(actionName);

                if (theActionMI != null)
                {
                    //使用指定的参数调用当前实例所表示的方法或构造函数
                    return theActionMI.Invoke(this, actionPars);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                loger.WriteLog("LoginBean.Action", e, LogLevel.Error, typeof(LoginBean));

                return null;
            }
        }
下面作为知识补充简单介绍下反射:
       反射(reflection)对象用于在运行时获取类型信息。该类位于System.Reflection命名空间中,可访问一个正在运行的程序的元数据。System.Reflection命名空间包含了允许您获取有关应用程序信息及向应用程序动态添加类型、值和对象的类。
       反射的用途:
       1、允许在运行时查看属性(attribute)信息。
       2、允许延迟绑定的方法和属性(property)。
       3、允许在运行时创建新类型,然后使用这些类型执行一些任务。
System.Reflection类的MemberInfo对象需要被初始化,用户发现与类相关的属性(attribute)。       

       又一次深入的了解了特性和反射,发现实际上它的作用类似与Spring.IOC。利用容器的主动推送实现灵活调用。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐