What I'm doing is creating a dynamic type from System.Data.DataTable through reflection. But i'm stuck when implementing an Interface to my dynamic type created by TypeBuilder.
My Interface looks like this
public interface ICustomViewCols
{
int? CardId { get; set; }
DateTime? OutDate { get; set; }
string HospCode { get; set; }
}
And my TypeBuilder looks like
var aName = new AssemblyName("UniWeb.CustomView");
var ab =
AssemblyBuilder.DefineDynamicAssembly(aName,
AssemblyBuilderAccess.RunAndCollect);
var mb =
ab.DefineDynamicModule(aName.Name + ".dll");
var tb = mb.DefineType(
"CustomViewModel",
TypeAttributes.Public);
tb.AddInterfaceImplementation(typeof(ICustomViewCols));
foreach (var obj in cols)
{
var col = obj as DataColumn;
var propType = GetNullableDataType(col.DataType);
var propName = col.ColumnName;
if (propName == "HospCode" || propName == "CardId" || propName == "OutDate")
{
var getMethod = typeof(ICustomViewCols).GetProperty(propName).GetGetMethod();
var setMethod = typeof(ICustomViewCols).GetProperty(propName).GetSetMethod();
var currGetPropMthdBldr = tb.DefineMethod($"get_{propName}",
MethodAttributes.Public | MethodAttributes.Virtual,
propType, Type.EmptyTypes);
var getIl = currGetPropMthdBldr.GetILGenerator();
getIl.Emit(OpCodes.Ret);
tb.DefineMethodOverride(currGetPropMthdBldr, getMethod);
var currSetPropMthdBldr = tb.DefineMethod($"set_{propName}",
MethodAttributes.Public | MethodAttributes.Virtual,
null, new[] { propType });
var setIl = currGetPropMthdBldr.GetILGenerator();
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldc_I4_1);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Callvirt, setMethod);
setIl.Emit(OpCodes.Ret);
tb.DefineMethodOverride(currSetPropMthdBldr, setMethod);
}
else
{
var field = tb.DefineField(propName, propType, FieldAttributes.Public);
var property = tb.DefineProperty(propName, PropertyAttributes.None, propType,
new Type[] {propType});
var GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;
var currGetPropMthdBldr =
tb.DefineMethod($"get_{propName}", GetSetAttr, propType, new Type[] {propType}); // Type.EmptyTypes);
var currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
var currSetPropMthdBldr =
tb.DefineMethod($"set_{propName}", GetSetAttr, null, new Type[] {propType});
var currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
}
var customViewType = tb.CreateType();
And this works only for the getters in my interface but not work for the setters. It throws an exception of System.InvalidOperationException: Method 'set_HospCode' does not have a method body. Could anybody help me out?
Aucun commentaire:
Enregistrer un commentaire