鳕鱼天空

This is Mr Wang's Tech Blog.

不可不知的C#基础 1. -- Extension 扩展方法

背景

前几天有同事问到我一个简单的功能, 就是当你使用枚举时如何给每个一元素增加描述字符串并且可以很容易的读取出来.

 

比如有一个枚举类型是列出对一个问题给出的选项(例如: 同意?不同意?中立?):

public enum AssessmentAnswer
 {
     Strongly_Disagree = 1,
     Disagree = 2,
     Neutral = 3,
     Agree = 4,
     Strongly_Agree = 5
 }


当选择不同的答案时, 希望得到一些描述性的语句比方说:

1. "强烈的反对"

2. "反对"

3. "持中立观点"

4. "同意"

5. "完全的同意"

 

当然你可以建立一个数据库表格,存放这些信息, 但是我想起几年前,我在网上下载一个 EnumDescription 源码(忘记了是在哪里下载的), 就可以实现这一功能.

让我们一起来看看是怎么样用 Extension 做到的:

实现

首先定义一个EnumDescription 类:

public class EnumDescription : Attribute
{
     public string Text
     {
         get { return _text; }
     } private string _text;

     public EnumDescription(string text)
     {
         _text = text;
     }
}

注意它的父类是Attribute, 因为我们希望将描述的语句作为每一个对应元素的特性. 然后新建一个文件,命名EnumExtensions.cs

public static class EnumExtensions
{
    public static string ToDescription(this Enum enumeration)
    {
        Type type = enumeration.GetType();
        MemberInfo[] memInfo = type.GetMember(enumeration.ToString());

        if (null != memInfo && memInfo.Length > 0)
        {
            object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumDescription), false);
            if (null != attrs && attrs.Length > 0)
                return ((EnumDescription)attrs[0]).Text;
        }

        return enumeration.ToString();
    }
}

在这里我们定义了一个扩展函数ToDescription, 就像所有的扩展函数一样,它的参数是类似(this …),

这个函数首先用GetType 得到了当前枚举的类型, 然后借助 GetMember按照元素的名字(值), 得到这个特定的元素, 最后用GetCustomAttributes 得到描述的内容.

 

这个扩展函数实现后,我们可以修改枚举的定义,加入描述:

public enum AssessmentAnswer
{
[EnumDescription("强烈的反对")]
Strongly_Disagree = 1,

    [EnumDescription("反对")]
    Disagree = 2,
    Neutral = 3,
    Agree = 4,
    [EnumDescription("完全的同意")]
    Strongly_Agree = 5
}

当要获取描述语句时, 你可以轻松的调用ToDescription :

//返回 "强烈的反对"

AssessmentAnswer.Strongly_Disagree.ToDescription()

注意, 如果没有给元素加入特性, 你仍旧可以使用ToDescription, 可以参考上面的代码看看是为什么.

//返回 “Disagree”

AssessmentAnswer.Disagree.ToDescription()

总结

扩展方法作为特殊的静态方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。

 

给初学者的话: 一旦当你实现扩展方法后, 你只需要复制dll 添加文件命名空间; 或者复制cs文件到你的项目中, 就可以使用这些方法,  但是建议除非你有充分的理由才实现扩展方法。

很多我们要用到的扩展方法都可以在网上得到, 所以一般在写自己的扩展前请先搜索一下.

 

 

 

 

Add comment

Loading