[开发故事]第四回:应用反射在运行时动态获取类型信息

anytao.net | 《你必须知道的.NET》网站 | Anytao技术博客 

发布日期:2009.05.12 作者:Anytao
© 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处。

//5.12,愿逝者安息,生者坚强

 

开发故事,开发中的小故事。

引言

网友hbfly,对于我在[你必须知道的.NET]第三十回:.NET十年(下)一文中关于“当应用attribute进行运行时反射”的论述,希望举例说明,他提出了自己的想法:

[MyAttribute("text.....")] 
public mymethod() 
{ 
    //我可以再方法内部得到attrib的text吗? 
}

我的回答是:当然可以了:-)那么,关于怎么做,就是个小问题。

呵呵,那么我们就一个小例子来技术如何在运行时通过反射获取MyAttribute中的字符串信息。

实现

既然是在运行时动态获取信息,那么这意味着我们可以通过反射获取任何类型信息,包括:Type、MethodInfo、PropertyInfo、FieldInfo、ParameterInfo都是可以手到擒来的。通过反射如何获取,而这些信息如何而来,我用三篇文章对此进行过详细的论述:

有兴趣可以参考一下。

所以,动态获取类型信息,是反射的拿手好戏,为了做以简单的说明,我就针对hbfly提出的问题实现一个解决方案,首先实现一个自定义的TextAttribute:

// Release : code01, 2009/05/12
// Author  : Anytao, http://www.anytao.com
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class TextAttribute : Attribute
{
    private readonly string text;

    public TextAttribute(string text)
    {
        this.text = text;
    }

    public string Text
    {
        get { return this.text; }
    }
}

其中定义了一个Text字段用于标记在运行时获取的信息,例如:

// Release : code02, 2009/05/12
// Author  : Anytao, http://www.anytao.com
[Text("Hello, Anytao")]
public class Hello
{
}

那么,我们的目的就是在运行时动态获取为Hello类标识的“Hello, Anytao”信息。

为了应用的简单性,我打算对object进行扩展,实现一个GetAttributeText 扩展方法,在实际的应用中,除特殊情况不建议对object实现扩展,否则将造成全局性的扩展,对于框架而言并非好事儿。好了,我们继续,看看如何在扩展方法中应用反射来实现想要的动态效果:

// Release : code03, 2009/05/12
// Author  : Anytao, http://www.anytao.com
public static class TextAttributeExtension
{
    public static string GetAttributeText(this object obj)
    {
        Type t = obj.GetType();
        var attr = t.GetCustomAttributes(typeof(TextAttribute), true).SingleOrDefault();

        if (attr == null)
        {
            throw new Exception("There is no TextAttribute to " + t.Name.ToString());
        }
   
        return ((TextAttribute)attr).Text;
    }
}

哈哈,大功告成。其实对hbfly而言,最重要的关注就在于通过反射的手段实现对于Attribute信息的读取,在我们的示例中,就是通过GetCustomAttributes方法来实现的。同样的道理,在Type类中还定义了很多的方法应用在不同的目标元素上,例如:

  • GetEvents/GetEvent
  • GetConstructors/GetConstructor
  • GetFields/GetField
  • GetGenericArguments
  • GetInterface
  • GetMembers/GetMember
  • GetMethods/GetMethod
  • GetNestedTypes/GetNestedType
  • GetProperties/GetProperty
  • ……

有了自定义的TextAttribute,有了对于object的扩展方法GetAttributeText,我们就可以实现动态获取类型信息的目标了:

// Release : code04, 2009/05/12
// Author  : Anytao, http://www.anytao.com
static void Main(string[] args)
{
    Hello hello = new Hello();
    Console.WriteLine(hello.GetAttributeText());

    MyClass mc = new MyClass();
    Console.WriteLine(mc.GetAttributeText());
}

不信,你运行试试。

结论

一个简单的技巧,一个补充的说明(对hbfly老兄的)。反射的能量是强大的,强大到我们可以轻而易举的对元数据信息进行读取和操作,正是如此很多基于Attribute和Reflection的巧妙设计就油然而生了。例如,在我的项目中就通过定义Attribute来实现实体类的string属性在get/set时统一进行Trim操作,保证了提交数据没有冗余,同时不必在其他地方来特别关注实现对于string.Trim()的调用。

参考文献

更多精彩,尽在anytao.net

 

anytao | © 2009 Anytao.com

2009/05/12 | http://anytao.net | http://anytao.net/blog/post/2009/05/12/anytao-devstory-06-dynamictypeinfo.aspx

本文以“现状”提供且没有任何担保,同时也没有授予任何权利。 | This posting is provided "AS IS" with no warranties, and confers no rights.

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2009-05-12 11:21  Anytao  阅读(5646)  评论(30编辑  收藏  举报