此属性(Attribute )而非彼属性(Property)。MSDN描述:属性(Attribute )能够提供功能强大的方法,以将声明信息与 C# 代码(类型、方法、属性等)相关联。一旦属性与程序实体关联,即可在运行时使用名为反射的技术对属性进行查询。属性 (Attribute) 描述如何将数据序列化,指定用于强制安全性的特性,并限制实时 (JIT) 编译器的优化,从而使代码易于调试。属性 (Attribute) 还可以记录文件名或代码作者,或在窗体开发阶段控制控件和成员的可见性等等。
MC"cl3uC0:n5`&KASZ0属性具有以下特点:
p.VM:bee!Ub01、属性可向程序中添加元数据。元数据是嵌入程序中的信息,如编译器指令或数据描述。
j2Gibgl
S*U02、程序可以使用反射检查自己的元数据。请参见使用反射访问属性。
'Gy4K
u4r_4W03、通常使用属性与 COM 交互。
ho:OGGe0ITPUB个人空间h.^;USI2nx#KA经过对属性的研究我们做一个小示例,用于阐明属性的使用。我们尝试写个方法,它以两个对象为参数,然后将源对象运行时的所有字段值都拷贝给目标对象。按照一般情况,只要是可序列化的类、字段和方法都可以通过反射机制完成上述操作。但是如果遇到[NonSerialized]限定的字段我们将无从下手。面对这种情形我们创建一个方法,不仅可以存取[Serialized]限定的字段,还可以还原那些经[NonSerialized]限定的字段并在运行时重新赋值!
@{lb9d
Kk0ITPUB个人空间GJ%@[@0e(@我们先创建一个可序列化的类:
ITPUB个人空间
V;F5x` H[Serializable]
Ld.SQQ C0public class FooClass
5n5\f+]|l$w0{
ITPUB个人空间V#I;r q5F)Rr public int data1;
ITPUB个人空间EHA
o/}$|#G(A5Mp [NonSerialized] public int data2;
ITPUB个人空间v~:~F$Q3U public FooClass(int data1, int data2)
ITPUB个人空间)h,jx;\\2{0J {
] d`F ^%D ]0 this.data1 = data1;
ITPUB个人空间hr8o&l)b
H
E,e.x this.data2 = data2;
ITPUB个人空间1Px"fM*MN!mR)A6YNZ }
h:U:p`ATjZs1{0}
Nh;S!V
s(G!j0 R2?%U)Kp&Z*AE+u0然后在Button1的Click事件中添加如下代码:
ITPUB个人空间 sT
_6heC private void button1_Click(object sender, EventArgs e)
sx"A%f${I&L3p*l0 {
ITPUB个人空间z:e/Hf0E FooClass destObject = new FooClass(10, 20);
,e9|p,rb^(h8t5FD2Y0 FooClass sourceObject = new FooClass(10, 30);
e+G(kyU]N:Y\0 MessageBox.Show("destObject.data2: "+destObject.data2+'\n'+"sourceObject.data2: "+sourceObject.data2);
ITPUB个人空间v]Zl?[r3mKS RestoreUtils.RestoreNonSerialized(destObject, sourceObject);
ITPUB个人空间rIv^v'Lq0P%`S MessageBox.Show("destObject.data2: " + destObject.data2 + '\n' + "sourceObject.data2: " + sourceObject.data2);
ITPUB个人空间3gw$B-w\4d
lm&a }
rb#Dr9H0ITPUB个人空间$Q.hcGIu
Ov0l运行结果如下:
g1Kn'U'kfE W0
.oF,C~+T"l0.lSR+p!}!Gx0注意,RestoreUtils.RestoreNonSerialized()方法,
{$Jgz,l%M8O0 public class RestoreUtils
ITPUB个人空间0d1dP6xl Q}2vJ%e {
ITPUB个人空间
wx:?'c&F
avRU const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
ITPUB个人空间qO4T`ZW1Q@0L2a7LV:z
?g'j)g.p0 public static void RestoreNonSerialized(object dest, object source)
t;T0h![M-KoT0 {
ITPUB个人空间1@^"f?;P}8z0N\3F ` if (dest == null || source == null)
ITPUB个人空间#d\#e6d8M8kx4tP.E;i2|#i return;
ITPUB个人空间 z
pMZ p${Wp{)R&H~
`&r0 Type bjectType = dest.GetType();
ITPUB个人空间 q4C3HO`NVf if (objectType.IsPrimitive | objectType.IsValueType)
ITPUB个人空间`e7yhDZQ[^*q return;
2A`7` ~p*A1p4OFUF_0ITPUB个人空间,DbL$AE)nd FieldInfo[] dstFieldsInfo = objectType.GetFields(flags);
3_*j%CZj_#b2tZ0 FieldInfo[] srcFieldsInfo = source.GetType().GetFields(flags);
9|u)O7dgB(Jq0\Nv*s?(R^_+g0 for (int fieldIndex = 0; fieldIndex < dstFieldsInfo.Length; fieldIndex++)
#T.knY7]}@0 {
0@*ud ^ V;P;l%L0 FieldInfo fieldInfo = dstFieldsInfo[fieldIndex];
ITPUB个人空间N T5ng3nbn8BmV if (fieldInfo.IsNotSerialized)
7Z
U%k.PG3`K0 {
ITPUB个人空间TNb5Xt%u?8t?
pV object newValue = srcFieldsInfo[fieldIndex].GetValue(source);
)]^4MU]1Y0 fieldInfo.SetValue(dest, newValue);
ITPUB个人空间9ZR1f1KW!m continue;
ITPUB个人空间$kO._4NJ^ph }
ITPUB个人空间?#So{YgOITPUB个人空间,m _qaOe)S object dstFieldObject = fieldInfo.GetValue(dest);
z1cY:Q)P.f7H
R^0 object srcFieldObject = srcFieldsInfo[fieldIndex].GetValue(source);
H*M.H,RU4?]z7e0 if (dstFieldObject != null && srcFieldObject != null)
ITPUB个人空间%Qg~ByKjM RestoreNonSerialized(dstFieldObject, srcFieldObject);
ITPUB个人空间6R$t]g2n|Xf[0rY }
!P9p!W/buH
NPWhz0&S!si*s5mG0 IEnumerable dstEnumerable = dest as IEnumerable;
ITPUB个人空间,weC(p0GzV if (dstEnumerable != null)
ITPUB个人空间R_A \!JU-c9d {
ITPUB个人空间/Oq0W
R3qqQ_L4R ^\G IEnumerable srcEnumerable = source as IEnumerable;
ITPUB个人空间5p2E4As.[i if (srcEnumerable != null)
^%\Z!v2o7z&|Q8f3lR0 {
ITPUB个人空间y:d _6~V5?H$? IEnumerator srcEnumerator = srcEnumerable.GetEnumerator();
.tB0`/[VMV0 foreach (Object dstItem in dstEnumerable)
ITPUB个人空间*[c$^1K`[-V {
:U.W5gim e:R0 bool next = srcEnumerator.MoveNext();
CC:o(L,_Nq0U0 if (!next)
ITPUB个人空间)_ab$v?Q8o*j break;
@},E)N:O
Y0 Object srcItem = srcEnumerator.Current;
Ad3CSqT.vKW0ITPUB个人空间1G:e/eZ
] RestoreNonSerialized(dstItem, srcItem);
]L6jVf|Zf0 }
k
T-WOpt
uSO:c0 }
ITPUB个人空间^"lA$?3pffD{:K*_ }
.g1E"VMP&x)^R0 }
+q|#}u$J_DTQ"`0 }
6h mQx*PkZY
Q0+aJ CbH@0我们会发现,FooClass类的data2字段为不可序列化字段,在没有还原不可序列化的字段之前,destObject.data2和sourceObject.data2的值是不同的,为20和30,当我们还原并将sourceObject.data2在运行时的值拷贝给destObject.data2后,两个FooClass类的实例的data2字段就完全一样了。
ITPUB个人空间'b.acx jCq:\7O6GR4r[3S4O2Ka!Z!p0