此属性(Attribute )而非彼属性(Property)。MSDN描述:属性(Attribute )能够提供功能强大的方法,以将声明信息与 C# 代码(类型、方法、属性等)相关联。一旦属性与程序实体关联,即可在运行时使用名为反射的技术对属性进行查询。属性 (Attribute) 描述如何将数据序列化,指定用于强制安全性的特性,并限制实时 (JIT) 编译器的优化,从而使代码易于调试。属性 (Attribute) 还可以记录文件名或代码作者,或在窗体开发阶段控制控件和成员的可见性等等。
"@#LuWd0{C0z]Q1B]:s%I0属性具有以下特点:
ITPUB个人空间a+i}
KZ
uD6x^1、属性可向程序中添加元数据。元数据是嵌入程序中的信息,如编译器指令或数据描述。
vR(]4A%wUS02、程序可以使用反射检查自己的元数据。请参见使用反射访问属性。
ITPUB个人空间&[?9_S1gl[:D3、通常使用属性与 COM 交互。
ITPUB个人空间b9qKK"l-u;s VA]R/y0经过对属性的研究我们做一个小示例,用于阐明属性的使用。我们尝试写个方法,它以两个对象为参数,然后将源对象运行时的所有字段值都拷贝给目标对象。按照一般情况,只要是可序列化的类、字段和方法都可以通过反射机制完成上述操作。但是如果遇到[NonSerialized]限定的字段我们将无从下手。面对这种情形我们创建一个方法,不仅可以存取[Serialized]限定的字段,还可以还原那些经[NonSerialized]限定的字段并在运行时重新赋值!
ITPUB个人空间)YK L;~X*ZJ&\ITPUB个人空间[-~*NqAFd/z'b-w我们先创建一个可序列化的类:
ITPUB个人空间"mk*j_"pow[Serializable]
ITPUB个人空间r:x
[^ucKP4i
rpublic class FooClass
E:OV;cM5D%M}`;\0{
ITPUB个人空间Q4d:_&Txt public int data1;
ITPUB个人空间3Aad M8P3dFC~6_ [NonSerialized] public int data2;
ITPUB个人空间?:C6v?$p public FooClass(int data1, int data2)
b+G4~ f@Q0 {
3B/fDRB*o0 this.data1 = data1;
X9]+\#d@0 this.data2 = data2;
1|6]nDk D0 }
ITPUB个人空间(D9|
dD0Kb}
z'Ri'm,@E&Q;?rR}0xx
Nrh0然后在Button1的Click事件中添加如下代码:
hA.CS*{0 private void button1_Click(object sender, EventArgs e)
+}RPf?7},]d~0 {
ITPUB个人空间K}j~ PJ%[ g%c FooClass destObject = new FooClass(10, 20);
GO'q
i0EW9n;W0 FooClass sourceObject = new FooClass(10, 30);
ITPUB个人空间;ze}5lM.PLE MessageBox.Show("destObject.data2: "+destObject.data2+'\n'+"sourceObject.data2: "+sourceObject.data2);
ITPUB个人空间h%l)K |kX RestoreUtils.RestoreNonSerialized(destObject, sourceObject);
6m/hn
Qjx7RyF0 MessageBox.Show("destObject.data2: " + destObject.data2 + '\n' + "sourceObject.data2: " + sourceObject.data2);
%vAh0Hx4`1R pS0 }
ITPUB个人空间'??K&k]:|#tITPUB个人空间d!ww;zf运行结果如下:
ITPUB个人空间-OV@,|OCX1k
Oc^*Gb#P3\0ITPUB个人空间.z&m7na)C注意,RestoreUtils.RestoreNonSerialized()方法,
ITPUB个人空间"aI6o2H/m$w public class RestoreUtils
-`*h
s*G3Xo0 {
3Mx;K tN0 const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
_ a3qr*C7k_04W/MdAL)GbEE#\0 public static void RestoreNonSerialized(object dest, object source)
ITPUB个人空间~H2\0r0~ {
ITPUB个人空间c8Z I1[le
A
p;w%m!G y if (dest == null || source == null)
vnI_Jt)[0 return;
.g:Cih
t&t/B0DM1g!a5GpT0`0 Type bjectType = dest.GetType();
KWB,W.K0 if (objectType.IsPrimitive | objectType.IsValueType)
-dV H\)yS DY e(F0 return;
,x
r
RLM.v0ITPUB个人空间u3Td*R5aMH
A FieldInfo[] dstFieldsInfo = objectType.GetFields(flags);
D%z.ja'n!a
^IU!\4L0 FieldInfo[] srcFieldsInfo = source.GetType().GetFields(flags);
gq t6g,P0W8e1o9Gw0 for (int fieldIndex = 0; fieldIndex < dstFieldsInfo.Length; fieldIndex++)
d!r!e1O3{;d0 {
ITPUB个人空间h#N5W%AR{ FieldInfo fieldInfo = dstFieldsInfo[fieldIndex];
ITPUB个人空间#GIMSr_5R)_ if (fieldInfo.IsNotSerialized)
#pT)] a ? \0 {
.O,\O z;AX#c0 object newValue = srcFieldsInfo[fieldIndex].GetValue(source);
b:m0y
|%YK0 fieldInfo.SetValue(dest, newValue);
ITPUB个人空间&I;fL5Z']3Ls continue;
ITPUB个人空间wha)t!Abw)@5]
z }
)@h3jo@W,v0yJ2~SsUx:[$`0 object dstFieldObject = fieldInfo.GetValue(dest);
ITPUB个人空间lS;W6co|
NF'_(W!j object srcFieldObject = srcFieldsInfo[fieldIndex].GetValue(source);
t%VN
DV\ut6c9{Q0 if (dstFieldObject != null && srcFieldObject != null)
ITPUB个人空间Tk2v ??zd RestoreNonSerialized(dstFieldObject, srcFieldObject);
ITPUB个人空间:D)E1n~
tix }
f0ZlW(d0Y0ITPUB个人空间7c(t.x$X,jtn[2a4a IEnumerable dstEnumerable = dest as IEnumerable;
ITPUB个人空间-DfSl8O6x/? d if (dstEnumerable != null)
ITPUB个人空间m8gi;h| {
H+T1nSV0 IEnumerable srcEnumerable = source as IEnumerable;
ITPUB个人空间2zX!S/N#W#g1pb if (srcEnumerable != null)
ITPUB个人空间/V&H6]#|FJ(N {
ITPUB个人空间r;LC|3D6s8F4Kv IEnumerator srcEnumerator = srcEnumerable.GetEnumerator();
6H? Pzftw*Q?"d0 foreach (Object dstItem in dstEnumerable)
ITPUB个人空间Jd(T+H!hVeF {
U%\0^9r!a U0 bool next = srcEnumerator.MoveNext();
ITPUB个人空间hgoXvN-w5f if (!next)
6M-q*B
K]
c0 break;
y`*`yB{#Nj0 Object srcItem = srcEnumerator.Current;
]a.jr0a0ITPUB个人空间#| U0m)@l RestoreNonSerialized(dstItem, srcItem);
dc9pT;{)|
Y0 }
8n!jOy@Um0 }
8[ o!m&Sh6M;G0 }
N;vO R5NX0 }
u?w&]:B%g$F2e7I(D#s0 }
ITPUB个人空间d;XD+Qm E'BUz|*~TQ$} g0我们会发现,FooClass类的data2字段为不可序列化字段,在没有还原不可序列化的字段之前,destObject.data2和sourceObject.data2的值是不同的,为20和30,当我们还原并将sourceObject.data2在运行时的值拷贝给destObject.data2后,两个FooClass类的实例的data2字段就完全一样了。
ITPUB个人空间]#xu#HXZ(dnITPUB个人空间!t0}Tr&T;`%e)q[