如何动态的生成一个实现 System.ComponentModel.INotifyPropertyChanged 的类的定义?
如何动态的生成一个实现 System.ComponentModel.INotifyPropertyChanged 的类的定义?
这个动态类中有形如 A、B、C、D、E、F等多个动态的属性。
public class ClassA: System.ComponentModel.INotifyPropertyChanged
{
string AField;
public string A
{
get
{
return this.AField;
}
set
{
if ((object.ReferenceEquals(this.AField, value) != true))
{
this.AField = value;
this.RaisePropertyChanged("A");
}
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null))
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
附: 已知生成一个简单的 getter setter 的属性的代码如下:
/// <summary>
/// 添加一个public属性,并且会创建对应的名为 propertyNm + "Field" 的私有字段
/// </summary>
/// <param name="propertyNm"></param>
/// <param name="type"></param>
/// <param name="canGet">是否实现getter</param>
/// <param name="canSet">是否实现setter</param>
public void AppendPublicProperty(string propertyNm, Type type, bool canGet, bool canSet)
{
FieldBuilder field = this.tb.DefineField(propertyNm + "Field", type, FieldAttributes.Private);
PropertyBuilder property = tb.DefineProperty(propertyNm, PropertyAttributes.HasDefault, type, null);
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
if (canGet)
{
MethodBuilder getAccessor = tb.DefineMethod("get_" + propertyNm, getSetAttr, type, Type.EmptyTypes);
ILGenerator getIL = getAccessor.GetILGenerator();
// For an instance property, argument 默认值 is the instance. Load the
// instance, then load the private field and return, leaving the
// field value on the stack.
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, field);
getIL.Emit(OpCodes.Ret);
property.SetGetMethod(getAccessor);
}
if (canSet)
{
MethodBuilder setAccessor = tb.DefineMethod("set_" + propertyNm, getSetAttr, null, new Type[] { type });
ILGenerator setIL = setAccessor.GetILGenerator();
// Load the instance and then the numeric argument, then store the
// argument in the field.
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, field);
setIL.Emit(OpCodes.Ret);
property.SetSetMethod(setAccessor);
}
}