此属性(Attribute )而非彼属性(Property)。MSDN描述:属性(Attribute )能够提供功能强大的方法,以将声明信息与 C# 代码(类型、方法、属性等)相关联。一旦属性与程序实体关联,即可在运行时使用名为反射的技术对属性进行查询。属性 (Attribute) 描述如何将数据序列化,指定用于强制安全性的特性,并限制实时 (JIT) 编译器的优化,从而使代码易于调试。属性 (Attribute) 还可以记录文件名或代码作者,或在窗体开发阶段控制控件和成员的可见性等等。
ITPUB个人空间3^ b
?8Q7rITPUB个人空间t}(SAuH~;j属性具有以下特点:
ITPUB个人空间8Ij |PE;TX\1\
`8?1、属性可向程序中添加元数据。元数据是嵌入程序中的信息,如编译器指令或数据描述。
ITPUB个人空间
_ h+z$qS+a]t2、程序可以使用反射检查自己的元数据。请参见使用反射访问属性。
ITPUB个人空间 I)V%Z3Zj/Q
s$LJS3、通常使用属性与 COM 交互。
I](g]:t+D0S{,B \ B5M/y{EUg'M0经过对属性的研究我们做一个小示例,用于阐明属性的使用。我们尝试写个方法,它以两个对象为参数,然后将源对象运行时的所有字段值都拷贝给目标对象。按照一般情况,只要是可序列化的类、字段和方法都可以通过反射机制完成上述操作。但是如果遇到[NonSerialized]限定的字段我们将无从下手。面对这种情形我们创建一个方法,不仅可以存取[Serialized]限定的字段,还可以还原那些经[NonSerialized]限定的字段并在运行时重新赋值!
Lu&^!POE,h0ITPUB个人空间B/qVrt|SC我们先创建一个可序列化的类:
h}%kzks0[Serializable]
r2R8wTWV.`0public class FooClass
ITPUB个人空间-[W B ^\ f{
LU!kN!R,@ e0 public int data1;
PUrcQ0 [NonSerialized] public int data2;
S`D/A$Xa'H0 public FooClass(int data1, int data2)
ITPUB个人空间 E c4i6p-S8Y {
dPC,BZ;Afc*S#u0 this.data1 = data1;
m+g1d,r~ he4W([0 this.data2 = data2;
ITPUB个人空间 E;vp+}?UCp!s+q(B }
ITPUB个人空间U%wdKX}
!U"?!H3]3dJ
F0G
mE
n$a(?c0然后在Button1的Click事件中添加如下代码:
9^k;w&gGf3{0 private void button1_Click(object sender, EventArgs e)
ITPUB个人空间%Q!`;gE&O.Y}Y!U2k {
ITPUB个人空间)N,L6QhH
T FooClass destObject = new FooClass(10, 20);
M5u.TitGObe8U0 FooClass sourceObject = new FooClass(10, 30);
X DG#Br/sNp0 MessageBox.Show("destObject.data2: "+destObject.data2+'\n'+"sourceObject.data2: "+sourceObject.data2);
ITPUB个人空间+{*JIi{ F2X@P0`s RestoreUtils.RestoreNonSerialized(destObject, sourceObject);
ITPUB个人空间y?G,|4x$f7T MessageBox.Show("destObject.data2: " + destObject.data2 + '\n' + "sourceObject.data2: " + sourceObject.data2);
;_ME:Tv p@g0 }
~8rW.?|6US-iJ*l0ITPUB个人空间K!`DM%n7`$~p
E9W@运行结果如下:
B)Md'q u md9~MW:V0
b
| JQQ%C08?1EN
Y;Og0注意,RestoreUtils.RestoreNonSerialized()方法,
ITPUB个人空间c'YEUe4B public class RestoreUtils
0ieU5f@0 {
$L(En"y6RF i2j(d|0 const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
ITPUB个人空间(OYw:f1J0Q4?i gITPUB个人空间1n#q(t%U6Y^ public static void RestoreNonSerialized(object dest, object source)
ITPUB个人空间 ?}h'Tsr~r'N {
ITPUB个人空间bi%n Kt!C }5f-d-y if (dest == null || source == null)
ITPUB个人空间$y:{VJ2p
U!K:g e return;
yOS*e_2j!}#x0%w)a
~U gG0t
h;MNh0 Type bjectType = dest.GetType();
,EC/n9O%sM%N_ V0 if (objectType.IsPrimitive | objectType.IsValueType)
P+\ N{8}U4M@qw0 return;
Hb4FNM6^p0&^2Z!a(ImZ'z0 FieldInfo[] dstFieldsInfo = objectType.GetFields(flags);
ie d3N5W
^;OE0 FieldInfo[] srcFieldsInfo = source.GetType().GetFields(flags);
ITPUB个人空间W~#x7R&u[m W"S1?X'WZ
XX0 for (int fieldIndex = 0; fieldIndex < dstFieldsInfo.Length; fieldIndex++)
ITPUB个人空间'[v c9m-w7d {
Y Z%IE {8k^0 FieldInfo fieldInfo = dstFieldsInfo[fieldIndex];
ITPUB个人空间oQ/E1ID if (fieldInfo.IsNotSerialized)
z2oXt"[9y"j2w,X~0 {
ITPUB个人空间0L!v)j}z_ object newValue = srcFieldsInfo[fieldIndex].GetValue(source);
ITPUB个人空间
f$p&QGX%L}{ fieldInfo.SetValue(dest, newValue);
Dh$yCjh!{HB0 continue;
6z;W8`ZABy8~H0 }
ITPUB个人空间2?:n
f
nyQ&^ITPUB个人空间-WT-|;f*ok'?;H object dstFieldObject = fieldInfo.GetValue(dest);
ITPUB个人空间o^+@:n"I2j!udyP,m6V object srcFieldObject = srcFieldsInfo[fieldIndex].GetValue(source);
2\?\"OF%h,a~7J0 if (dstFieldObject != null && srcFieldObject != null)
ap!I+SZ
``Y0 RestoreNonSerialized(dstFieldObject, srcFieldObject);
ITPUB个人空间fA8]x!TA#S }
ITPUB个人空间^
\"W1e'Du4rc(?1P d }q&QXi0\'o-z0 IEnumerable dstEnumerable = dest as IEnumerable;
ITPUB个人空间6QRjI e*E#y#O0]K if (dstEnumerable != null)
$|.oi3t%Ap&GQ0 {
ITPUB个人空间(Om&VDF0@M IEnumerable srcEnumerable = source as IEnumerable;
)beM4AFuL0 if (srcEnumerable != null)
g |^GpK0 {
x6J-c+JPFe0 IEnumerator srcEnumerator = srcEnumerable.GetEnumerator();
6S?2?0S#C0 foreach (Object dstItem in dstEnumerable)
:t;SQ1J
D0 {
|%P&{:VtyV?%x,a0 bool next = srcEnumerator.MoveNext();
5Ya,n#m,t0 if (!next)
+QkU2NyR6Py[~5i0 break;
C]vZr#}d4l!X0 Object srcItem = srcEnumerator.Current;
.?E*{ODvA0-W6j(Mwg0 RestoreNonSerialized(dstItem, srcItem);
ITPUB个人空间1NM^%k}#] }
b0{ }aKPrm&q"kE0 }
5J!`%q
Ge0 }
z:UH I%j2N1c
{0 }
ITPUB个人空间iR&d5v-A }
ITPUB个人空间OHX:oHITPUB个人空间@[c3b$a9O&^
^3S r7Q我们会发现,FooClass类的data2字段为不可序列化字段,在没有还原不可序列化的字段之前,destObject.data2和sourceObject.data2的值是不同的,为20和30,当我们还原并将sourceObject.data2在运行时的值拷贝给destObject.data2后,两个FooClass类的实例的data2字段就完全一样了。
ITPUB个人空间7Kr(u#Bi-D?_#H7Ij-d0