c#之Attribute特性的原理

简介: c#之Attribute特性的原理

当我们在Visual Studio添加一个自定义控件时,它都会给我们以下默认的代码。

[DefaultProperty("Text")]   
    [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]   
    public class WebCustomControl1 : WebControl   
    {   
        [Bindable(true)]   
        [Category("Appearance")]   
        [DefaultValue("")]   
        [Localizable(true)]   
        public string Text   
        {   
            get  
            {   
                String s = (String)ViewState["Text"];   
                return ((s == null) ? String.Empty : s);   
            }   
            set  
            {   
                ViewState["Text"] = value;   
            }   
        }   
        protected override void RenderContents(HtmlTextWriter output)   
        {   
            output.Write(Text);   
        }   
    }  
[DefaultProperty("Text")]
    [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
    public class WebCustomControl1 : WebControl
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["Text"] = value;
            }
        }
        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write(Text);
        }
    } 

在这个控件中有个默认的属性"Text",在这个属性有[DefaultValue("")]相应的特性,来给该属性设置默认值。以前一直

想不明白微软是怎么实现的,直到昨天看了《你必须知道的.Net》中讲“特性”这一章受到了启发。于是我马上去试试,

还真的可以。废话少说,来看看我的实现方法。

首先我们先创建一个自己默认值特性SelfDefaultValueAttribute:

[AttributeUsageAttribute(AttributeTargets.All,   //     可以对任何应用程序元素应用属性       
       AllowMultiple = true,                        //     允许指定多个实例      
       Inherited = false)]                          //     不继承到派生类   
   public  class SelfDefaultValueAttribute : System.Attribute   
   {   
       public SelfDefaultValueAttribute(object defaultVale)   
       {   
           this.AttrValue = defaultVale;   
       }   
       public object AttrValue   
       {   
           get;   
           set;   
       }   
   }  
 [AttributeUsageAttribute(AttributeTargets.All,   //     可以对任何应用程序元素应用属性    
        AllowMultiple = true,                        //     允许指定多个实例   
        Inherited = false)]                          //     不继承到派生类
    public  class SelfDefaultValueAttribute : System.Attribute
    {
        public SelfDefaultValueAttribute(object defaultVale)
        {
            this.AttrValue = defaultVale;
        }
        public object AttrValue
        {
            get;
            set;
        }
    } 

接着我们创建一个自己的控件父类SelfControl

public  class SelfControl      
 { 
   public SelfControl()           
  {             
    Type tp = this.GetType();              
    PropertyInfo[] propInfoList = tp.GetProperties();   //获得所有的属性        
      foreach (PropertyInfo p in propInfoList)              
      {  
      //获得当前属性的特性                  
      SelfDefaultValueAttribute m = Attribute.GetCustomAttribute(p, typeof (SelfDefaultValueAttribute)) as SelfDefaultValueAttribute;                     
    //判断该属性是否有特性                   
    if (m != null)                   
    {                       
      //设置默认值                       
      p.SetValue(this, m.AttrValue, null);                   
    }                   
    else                  
    {                       
      //设置值为空                       
      p.SetValue(this, null, null);                   
    }               
    }           
  }
  [SelfDefaultValue("")]          
  public virtual string Name          
  {              
    get;              
    set;          
  }       
}   
public class SelfControl    
{  
    public SelfControl()        
   {            
      Type tp = this.GetType();            
      PropertyInfo[] propInfoList = tp.GetProperties();   
      //获得所有的属性
        foreach (PropertyInfo p in propInfoList)
            {
                SelfDefaultValueAttribute m = Attribute.GetCustomAttribute(p, typeof
(SelfDefaultValueAttribute)) as SelfDefaultValueAttribute;                //获得当前属性的特性
           /*判断该属性是否有特性*/
                if (m != null)
                {
                    /*设置默认值*/
                    p.SetValue(this, m.AttrValue, null);
                }
                else
                {
                    /*设置值为空*/
                    p.SetValue(this, null, null);
                }
            }
        }
       [SelfDefaultValue("")]
       public virtual string Name
       {
           get;
           set;
       }
    } 

这个控件只有一个属性"Name"默认值为空。说明一下的是,在这里我们用到了反射的机制,所以我们要引入空间:

System.Reflection。

现在,我们就可以创建属于自己定义的控件了。

好了,终于完成了。那我们现在来测试一下。

public class Myrun   
   {   
       public static void Main(string[] args)   
       {   
           TestSelfControl selfCon = new TestSelfControl();   
           Console.WriteLine("控件宽度:{0}",selfCon.Width);   
           Console.WriteLine("控件高度:{0}", selfCon.Height);   
           Console.WriteLine("控件名字:{0}", selfCon.Name);   
           Console.WriteLine("控件标签:{0}", selfCon.HtmlTag);   
           Console.WriteLine("控件文本:{0}", selfCon.Text);   
           Console.ReadLine();   
       }   
   }  
public class Myrun
   {
       public static void Main(string[] args)
       {
           TestSelfControl selfCon = new TestSelfControl();
           Console.WriteLine("控件宽度:{0}",selfCon.Width);
           Console.WriteLine("控件高度:{0}", selfCon.Height);
           Console.WriteLine("控件名字:{0}", selfCon.Name);
           Console.WriteLine("控件标签:{0}", selfCon.HtmlTag);
           Console.WriteLine("控件文本:{0}", selfCon.Text);
           Console.ReadLine();
       }
   } 
最后的结果就是:
view plaincopy to clipboardprint?
控件宽度:100   
控件高度:0   
控件名字:   
控件标签:   
控件文本:TestControl  
控件宽度:100
控件高度:0
控件名字:
控件标签:
控件文本:TestControl 

由于我们没给控件的高度设置默认值、高度类型Int,所以高度默认为0;而名字和标签类型为String,所以为空。

相关文章
|
6月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
6月前
|
编译器 C# 开发者
C# 11.0中的新特性:覆盖默认接口方法
C# 11.0进一步增强了接口的灵活性,引入了覆盖默认接口方法的能力。这一新特性允许类在实现接口时,不仅可以提供接口中未实现的方法的具体实现,还可以覆盖接口中定义的默认方法实现。本文将详细介绍C# 11.0中接口默认方法覆盖的工作原理、使用场景及其对现有代码的影响,帮助开发者更好地理解和应用这一新功能。
|
6月前
|
编译器 C# 开发者
C# 9.0中的顶级语句:简化程序入口的新特性
【1月更文挑战第13天】本文介绍了C# 9.0中引入的顶级语句(Top-level statements)特性,该特性允许开发者在不使用传统的类和方法结构的情况下编写简洁的程序入口代码。文章详细阐述了顶级语句的语法、使用场景以及与传统程序结构的区别,并通过示例代码展示了其在实际应用中的便捷性。
|
9天前
|
编译器 C# 开发者
C# 9.0 新特性解析
C# 9.0 是微软在2020年11月随.NET 5.0发布的重大更新,带来了一系列新特性和改进,如记录类型、初始化器增强、顶级语句、模式匹配增强、目标类型的新表达式、属性模式和空值处理操作符等,旨在提升开发效率和代码可读性。本文将详细介绍这些新特性,并提供代码示例和常见问题解答。
25 7
C# 9.0 新特性解析
|
8天前
|
C# 开发者
C# 10.0 新特性解析
C# 10.0 在性能、可读性和开发效率方面进行了多项增强。本文介绍了文件范围的命名空间、记录结构体、只读结构体、局部函数的递归优化、改进的模式匹配和 lambda 表达式等新特性,并通过代码示例帮助理解这些特性。
20 2
|
2月前
|
编译器 C# Android开发
震惊!Uno Platform 与 C# 最新特性的完美融合,你不可不知的跨平台开发秘籍!
Uno Platform 是一个强大的跨平台应用开发框架,支持 Windows、macOS、iOS、Android 和 WebAssembly,采用 C# 和 XAML 进行编程。C# 作为其核心语言,持续推出新特性,如可空引用类型、异步流、记录类型和顶级语句等,极大地提升了开发效率。要在 Uno Platform 中使用最新 C# 特性,需确保开发环境支持相应版本,并正确配置编译器选项。通过示例展示了如何在 Uno Platform 中应用可空引用类型、异步流、记录类型及顶级语句等功能,帮助开发者更好地构建高效、优质的跨平台应用。
202 59
|
27天前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
33 1
|
3月前
|
开发框架 .NET 编译器
总结一下 C# 如何自定义特性 Attribute 并进行应用
总结一下 C# 如何自定义特性 Attribute 并进行应用
|
3月前
|
C# 索引
C#各大版本特性
C#各大版本特性
76 0
|
6月前
|
开发框架 .NET Java
ASP.NET Core高级编程--C#基本特性(一)
本文章简略介绍C#的部分特性