C#自定义Attribute值的获取与优化

  C#自定义Attribute值的获取是开发中会经常用到的,一般我们的做法也就是用反射进行获取的,代码也不是很复杂。

1、首先有如下自定义的Attribute

 1     [AttributeUsage(AttributeTargets.All)]
 2     public sealed class NameAttribute : Attribute
 3     {
 4         private readonly string _name;
 5
 6         public string Name
 7         {
 8             get { return _name; }
 9         }
10
11         public NameAttribute(string name)
12         {
13             _name = name;
14         }
15     }

  2、定义一个使用NameAttribute的类

1     [Name("dept")]
2     public class CustomAttributes
3     {
4         [Name("Deptment Name")]
5         public string Name { get; set; }
6
7         [Name("Deptment Address")]
8         public string Address;
9     }

  3、获取CustomAttributes类上的"dept"也就很简单了

 1         private static string GetName()
 2         {
 3             var type = typeof(CustomAttributes);
 4
 5             var attribute = type.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault();
 6
 7             if (attribute == null)
 8             {
 9                 return null;
10             }
11
12             return ((NameAttribute)attribute).Name;
13         }

  以上代码就可以简单的获取,类上的Attribute的值了,但是需求往往不是这么简单的,不仅要获取类头部Attribute上的值,还要获取字段Address头部Attribute上的值。有的同学可能就觉得这还不简单呀,直接上代码

 1         private static string GetAddress()
 2         {
 3             var type = typeof (CustomAttributes);
 4
 5             var fieldInfo = type.GetField("Address");
 6             if (fieldInfo == null)
 7             {
 8                 return null;
 9             }
10
11             var attribute = fieldInfo.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault();
12
13             if (attribute == null)
14             {
15                 return null;
16             }
17
18             return ((NameAttribute) attribute).Name;
19         }

  上面代码就是获取Address字段头部上的Attribute值了。虽然我们是获取到了我们想要的,但是我们发现这样做是不是太累了,如果又扩展一个自定义的Attribute,或者又在一个新的属性或字段上标上Attribute时,我们又要写一段代码来实现我想要的,这些严重代码违反了DRY的设计原则。我们知道获取Attribute是通过反射来取的,Attribute那个值又是不变的,这样就没必要每次都要进行反射来获取了。基于以上两点代码进行了如下的优化,优化后的代码如下:

  1     public static class CustomAttributeHelper
  2     {
  3         /// <summary>
  4         /// Cache Data
  5         /// </summary>
  6         private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>();
  7
  8         /// <summary>
  9         /// 获取CustomAttribute Value
 10         /// </summary>
 11         /// <typeparam name="T">Attribute的子类型</typeparam>
 12         /// <param name="sourceType">头部标有CustomAttribute类的类型</param>
 13         /// <param name="attributeValueAction">取Attribute具体哪个属性值的匿名函数</param>
 14         /// <returns>返回Attribute的值,没有则返回null</returns>
 15         public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction) where T : Attribute
 16         {
 17             return GetAttributeValue(sourceType, attributeValueAction, null);
 18         }
 19
 20         /// <summary>
 21         /// 获取CustomAttribute Value
 22         /// </summary>
 23         /// <typeparam name="T">Attribute的子类型</typeparam>
 24         /// <param name="sourceType">头部标有CustomAttribute类的类型</param>
 25         /// <param name="attributeValueAction">取Attribute具体哪个属性值的匿名函数</param>
 26         /// <param name="name">field name或property name</param>
 27         /// <returns>返回Attribute的值,没有则返回null</returns>
 28         public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction,
 29             string name) where T : Attribute
 30         {
 31             return GetAttributeValue(sourceType, attributeValueAction, name);
 32         }
 33
 34         private static string GetAttributeValue<T>(Type sourceType, Func<T, string> attributeValueAction,
 35             string name) where T : Attribute
 36         {
 37             var key = BuildKey(sourceType, name);
 38             if (!Cache.ContainsKey(key))
 39             {
 40                 CacheAttributeValue(sourceType, attributeValueAction, name);
 41             }
 42
 43             return Cache[key];
 44         }
 45
 46         /// <summary>
 47         /// 缓存Attribute Value
 48         /// </summary>
 49         private static void CacheAttributeValue<T>(Type type,
 50             Func<T, string> attributeValueAction, string name)
 51         {
 52             var key = BuildKey(type, name);
 53
 54             var value = GetValue(type, attributeValueAction, name);
 55
 56             lock (key + "_attributeValueLockKey")
 57             {
 58                 if (!Cache.ContainsKey(key))
 59                 {
 60                     Cache[key] = value;
 61                 }
 62             }
 63         }
 64
 65         private static string GetValue<T>(Type type,
 66             Func<T, string> attributeValueAction, string name)
 67         {
 68             object attribute = null;
 69             if (string.IsNullOrEmpty(name))
 70             {
 71                 attribute =
 72                     type.GetCustomAttributes(typeof (T), false).FirstOrDefault();
 73             }
 74             else
 75             {
 76                 var propertyInfo = type.GetProperty(name);
 77                 if (propertyInfo != null)
 78                 {
 79                     attribute =
 80                         propertyInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault();
 81                 }
 82
 83                 var fieldInfo = type.GetField(name);
 84                 if (fieldInfo != null)
 85                 {
 86                     attribute = fieldInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault();
 87                 }
 88             }
 89
 90             return attribute == null ? null : attributeValueAction((T) attribute);
 91         }
 92
 93         /// <summary>
 94         /// 缓存Collection Name Key
 95         /// </summary>
 96         private static string BuildKey(Type type, string name)
 97         {
 98             if (string.IsNullOrEmpty(name))
 99             {
100                 return type.FullName;
101             }
102
103             return type.FullName + "." + name;
104         }
105     }

  以上优化后的代码:

  把不同的代码用泛型T,Fun<T,stirng>来处理来减少重复的代码;
  把取过的Attribute值存到一个Dictionary中,下次再来取时,如果有则直接返回Dictionary中的值,如果没有才通过反射来取相应的Attribute值,这样大大的提高效率;

  调用方法也更加的简单了,代码如下:

1             var cName=typeof(CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name);
2             var fName = typeof (CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name, "Address");

  有没有, 是不是很简单,而且调用方式对缓存是完全透明的!

  如果你有什么好的或不好的意见欢迎拍砖!

时间: 2024-08-25 23:22:34

C#自定义Attribute值的获取与优化的相关文章

获取自定义Attribute的Description

自定义Attribute /// <summary> /// 合同状态 /// </summary> public enum ContractStatus { [GlobalCode("新建")] Pending = 0, [GlobalCode("提交待审批")] AuditPending = 3, [GlobalCode("审批拒绝")] AuditReject = 6 } [AttributeUsage(Attrib

.net c#获取自定义Attribute

前言: 在c#开发中,有时候我们需要读取 Attribute中的信息(关于Attribute , 我自己把他理解成一个可以为类,属性标记的东西,这个标记可以为你提供一些关于类,方法,属性的额外信息) 我们如何获取这些标记的信息,如何获取自定义Attribute信息. 正文: 1.获取一个枚举的详细信息 假设我们有这样一个枚举 public enum Category { /// <summary> /// 英语 /// </summary> English, /// <sum

c#自定义Attribute获取接口实现

原文:c#自定义Attribute获取接口实现 一般的接口实现多态 定义接口 interface Ipeople { void say(); } 定义实现的类 public class man : Ipeople { public void say() { MessageBox.Show("man"); } } public class woman : Ipeople { public void say() { MessageBox.Show("woman"); }

转:C#制作ORM映射学习笔记一 自定义Attribute类

之前在做unity项目时发现只能用odbc连接数据库,感觉非常的麻烦,因为之前做web开发的时候用惯了ORM映射,所以我想在unity中也用一下ORM(虽然我知道出于性能的考虑这样做事不好的,不过自己的小项目吗管他的,自己爽就行了).不过现在世面上的ORM映射基本都是为web项目设计的,与unity项目很难契合,所以我决定自己做一个简易的ORM映射.虽然想的很美但是实际做起来才发现还是挺复杂的,所以我在这里记录一下这次的开发过程,防止以后遗忘. 今天先记录一下如何通过自定义attribute类实

自定义Attribute,使用记录

1. 自定义attribute需要继承Attribute基类 /// <summary> /// Datareader反射使用 标记 /// 标记 属性在Datareader 中的字段名 以便反射赋值 /// </summary> [AttributeUsage(AttributeTargets.Property| AttributeTargets.Field)] public class DataReaderModelAttribute:Attribute { private s

Webkit IDL中自定义[命名]属性的获取(Getter)以及设置(Setter)函数

一.自定义命名属性的获取(Getter)以及设置(Setter)函数: [CustomNamedGetter](i), [CustomNamedSetter](i) 命名属性的W3C链接如下:?The spec of named properties (注意,下面描述的webkit行为和W3C的规范是不同的) 总结: [CustomNamedGetter] 或者 [CustomNamedSetter] 允许你为命名属性的getter或者setter编写自己的绑定函数. 用法如下: [ Custo

向值栈获取List集合

-------------------siwuxie095 从值栈获取 List 集合 1.具体步骤 (1)在 Action 中向值栈放 List 集合 (2)在 JSP 页面中从值栈获取 List 集合 2.具体实现 (1)编写实体类 User.java: package com.siwuxie095.entity; // User 实体类 public class User { private String username; private String password; private

XsdGen:通过自定义Attribute与反射自动生成XSD

前言 系统之间的数据交互往往需要事先定义一些契约,在WCF中我们需要先编写XSD文件,然后通过自动代码生成工具自动生成C#对象.对于刚刚接触契约的人来说,掌握XMLSpy之类的软件之后确实比手写XML效率要高,但还是有些学习成本的.此外XML的tag太多,如果设计的类型属性过多,手写XSD也不太现实,很难专注于设计. 于是我想能不能先用C#写好类型,然后自动生成标准格式的XSD呢.经过三天左右的设计和实现,目前实现了以下功能: 1. 支持Class和Enum类型的设计 2. 支持基元类型.自定义

表单中单选、多选、选择框值的获取及表单的序列化

总结了下在表单处理中单选.多选.选择框值的获取及表单的序列化,写成了一个对象.如下: 1 var formUtil = { 2 // 获取单选按钮的值,如有没有选的话返回null 3 // elements为radio类的集合的引用 4 getRadioValue:function(elements) { 5 var value = null; // null表示没有选中项 6 // 非IE浏览器 7 if(elements.value != undefined && elements.v