起初一直纠结于如何调用特性附着在下面那个成员的值,后来发现不需要调用,通过反射加载的时候是自动绑定上去的,即 获得成员对象之后,有一个方法可以获得特性标签。
其实从类库提供者,和类库使用者的角度,分开来看就很容易理解了。
类库提供者(MyClassLib类):
MyClassLib类有一个ShowString(object obj, string name)方法,可以打印出string信息。
并且提供一个StringLenAttribute特性,控制字符串长度。
类库使用者:
使用这个名为MyClassLib的类,来打印信息
下面看例子
使用者:
public class User { [StringLen(3)] string myName; [StringLen(50)] string myDetail; public void Go() { myName = "Tim Cook"; myDetail = "Apple company CEO"; MyClassLib cl = new MyClassLib(); cl.ShowString(this, myName); cl.ShowString(this, myDetail); //Output: //字符串过长! 打印失败 //Apple company CEO } }
[StringLen(xx)]
这个是自定义的特性
来看看提供者方面的代码
提供者:
定义自定义特性:
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)] public sealed class StringLenAttribute : Attribute { public int Len { get; set; } public StringLenAttribute(int len) { this.Len = len; } }
然后是打印字符串这个方法,和应用特性:
public class MyClassLib { public void ShowString(object obj, string name) { var atts = obj.GetType().GetFields(BindingFlags.Instance|BindingFlags.NonPublic); foreach (var item in atts) { var tmp = item.GetCustomAttributes(typeof(StringLenAttribute), false); string tmp2 = string.Empty; if (tmp.Length > 0 && (string)item.GetValue(obj) == name) { var stringLenAtt = (StringLenAttribute)tmp[0]; if (name.Length > stringLenAtt.Len) { Console.WriteLine("字符串过长! 打印失败"); return; } } } Console.WriteLine(name); } }
反射调用的话,应该是必须得到对象才能使用里面成员,所以要传入2个参数,真正编写的时候肯定涉及自己的结构类,所以这个问题并不明显。如果以后找到解决方法,会更新这篇文章。