关于C#中的特性小例子

最近要写一个网络报表。

众所周知,网络报表是程序员的一大噩梦。

幸运的是,了解了下需求,然后去网络上大概看了下报表相关的信息。

感觉微软自带的RDLC报表能完全满足需求了。

不过,受伤的总是我。

老大一句:“要做成组件,下次调用直接拖拉就行,不需要手动操作!”

...

请问:天黑是神马感觉?!

这句话的意思就是要完全动态生成报表(不了解rdlc报表的童鞋们去操作下试试就知道了)。

里面要用到的技术,我大概想了一下。

主要就是XML的架构定义和序列号,反序列话。其他的没什么。不过,就这2个技术,让我感觉顿时落入了地狱(两个我都不熟悉。)。

没办法,只能硬着头皮搞了。

第一个遇到的问题就是c#特性机制了。

稍微看了下,懂了,就先记录下一些自认为经典的例子吧(2个小时前,我连这个[]叫特性都不知道,或者说都没怎么见过这个运算符这个用。2个小时看了几个代码,尤其是下面示例的代码,就懂了!)。

 

不多说,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BoardingCheckAttribute boardingCheck = null;
            object[] customAttributes = typeof(HumanPropertyBase).GetCustomAttributes(true);
            Console.WriteLine(typeof(HumanPropertyBase).IsSerializable);
            foreach (System.Attribute attribute in customAttributes)
            {
                if (attribute is BoardingCheckAttribute)
                {
                    boardingCheck = attribute as BoardingCheckAttribute;
                    Console.WriteLine(boardingCheck.Name
                        + "'s ID is "
                        + boardingCheck.ID
                        + ", he/she wants to "
                        + boardingCheck.Destination
                        + " from "
                        + boardingCheck.Departure
                        + " by the plane "
                        + boardingCheck.FlightNumber
                        + ", his/her position is "
                        + boardingCheck.PositionNumber
                        + ".");
                }
            }

            Console.ReadLine();
        }
    }
    [Serializable]
    [BoardingCheckAttribute("123","louis",22,12,"aaaa","ccccc")]
    public class HumanPropertyBase
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public int Gender { get; set; }

        [Obsolete("I'm so old, don't kill me!", true)]
        public void Run(int speed)
        {
            // Running is good for health.  
        }
    }

    public class BoardingCheckAttribute : Attribute
    {
        public string ID { get; private set; }
        public string Name { get; private set; }
        public int FlightNumber { get; private set; }
        public int PositionNumber { get; private set; }
        public string Departure { get; private set; }
        public string Destination { get; private set; }

        public BoardingCheckAttribute(string id, string name, int flightNumber, int positionNumber, string departure, string destination)
        {
            this.ID = id;
            this.Name = name;
            this.FlightNumber = flightNumber;
            this.PositionNumber = positionNumber;
            this.Departure = departure;
            this.Destination = destination;
        }

    }

}

 

 

[System.AttributeUsage(System.AttributeTargets.Class |
                       System.AttributeTargets.Struct,
                       AllowMultiple = true)  // multiuse attribute
]
public class Author : System.Attribute
{
    string name;
    public double version;

    public Author(string name)
    {
        this.name = name;
        version = 1.0;  // Default value
    }

    public string GetName()
    {
        return name;
    }
}

[Author("H. Ackerman")]
public class FirstClass
{
    // ...
}

// No Author attribute
public class SecondClass
{
    // ...
}

[Author("H. Ackerman"), Author("M. Knott", version = 2.0)]
public class ThirdClass
{
    // ...
}

class TestAuthorAttribute
{
    static void Main()
    {
        PrintAuthorInfo(typeof(FirstClass));
        PrintAuthorInfo(typeof(SecondClass));
        PrintAuthorInfo(typeof(ThirdClass));
    }

    private static void PrintAuthorInfo(System.Type t)
    {
        System.Console.WriteLine("Author information for {0}", t);
        System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // reflection

        foreach (System.Attribute attr in attrs)
        {
            if (attr is Author)
            {
                Author a = (Author)attr;
                System.Console.WriteLine("   {0}, version {1:f}", a.GetName(), a.version);
            }
        }
    }
}

 

网上搜到的解释:(对应第二段代码)

 

使用反射访问属性(C# 编程指南)
如果没有检索自定义属性的信息和对其进行操作的方法,则定义自定义属性并将其放置在源代码中就没有意义。C# 具有一个反射系统,可用来检索用自定义属性定义的信息。主要方法是 GetCustomAttributes,它返回对象数组,这些对象在运行时等效于源代码属性。此方法具有多个重载版本。有关更多信息,请参见 Attribute。

属性规范,如:

C#
[Author("H. Ackerman", version = 1.1)]
class SampleClass

在概念上等效于:

C#
Author anonymousAuthorObject = new Author("H. Ackerman");
anonymousAuthorObject.version = 1.1;

【备:我是第一次看到这个写法,然后兴匆匆的去试了下类的属性,发现这个写法不使用了。

   疑惑:难道这个写法只适用于特性的实例化么?如果高手见到,还请指教。】

但是,直到查询 SampleClass 以获取属性时才会执行此代码。对 SampleClass 调用 GetCustomAttributes 会导致按上述方式构造并初始化一个 Author 对象。如果类还有其他属性,则其他属性对象的以类似方式构造。然后 GetCustomAttributes 返回 Author 对象和数组中的任何其他属性对象。之后就可以对此数组进行迭代,确定根据每个数组元素的类型所应用的属性,并从属性对象中提取信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值