您的位置:首页 > 编程语言

动态实现接口 代码

2008-09-08 10:05 274 查看
lock (handlers.SyncRoot)
{
AppDomain currentAppDomain = AppDomain.CurrentDomain;
AssemblyName assyName = new AssemblyName();
assyName.Name = type.FullName;
AssemblyBuilder assyBuilder = currentAppDomain.DefineDynamicAssembly(assyName, AssemblyBuilderAccess.Run);
ModuleBuilder modBuilder = assyBuilder.DefineDynamicModule(type.FullName);
Type[] newTypeInterfaces;
newTypeInterfaces = new Type[] { typeof(IValueHandler) };
TypeBuilder typeBuilder =
modBuilder.DefineType(
"ValueHandler", TypeAttributes.Public);

typeBuilder.AddInterfaceImplementation(typeof(IValueHandler));
//PropertyInfo[] infos tmpInfos
PropertyInfo[] infos = type.GetProperties();

TypeBuilder pidBuilder =
modBuilder.DefineType(
"<PrivateImplementationDetails>", TypeAttributes.AutoClass | TypeAttributes.AnsiClass);
FieldBuilder getHashtableBuilder = pidBuilder.DefineField(
"$$method0x6000022-1", typeof(Hashtable), FieldAttributes.Static | FieldAttributes.Assembly);
FieldBuilder setHashtableBuilder = pidBuilder.DefineField(
"$$method0x6000023-1", typeof(Hashtable), FieldAttributes.Static | FieldAttributes.Assembly);
pidBuilder.CreateType();

MethodBuilder createInstanceMethodBuilder = typeBuilder.DefineMethod(
"CreateInstance", MethodAttributes.Public | MethodAttributes.Virtual,
typeof(object), null);
ILGenerator createGenerator = createInstanceMethodBuilder.GetILGenerator();
createGenerator.DeclareLocal(typeof(object));
ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
if (constructorInfo != null)
{
Label createRet = createGenerator.DefineLabel();
createGenerator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
createGenerator.Emit(OpCodes.Stloc_0);
createGenerator.Emit(OpCodes.Br_S, createRet);
createGenerator.MarkLabel(createRet);
createGenerator.Emit(OpCodes.Ldloc_0);
createGenerator.Emit(OpCodes.Ret);
}
else
{
createGenerator.Emit(OpCodes.Ldstr, "The object does not has default constructor");
createGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
createGenerator.Emit(OpCodes.Throw);
}

#region Get

MethodBuilder getMethodBuilder = typeBuilder.DefineMethod(
"GetValue", MethodAttributes.Public | MethodAttributes.Virtual,
typeof(object), new Type[] { typeof(object), typeof(string) });
ILGenerator getGenerator = getMethodBuilder.GetILGenerator();
getGenerator.DeclareLocal(typeof(object));
getGenerator.DeclareLocal(typeof(object));

Label L_0112 = getGenerator.DefineLabel();
Label L_0256 = getGenerator.DefineLabel();
Label getRet = getGenerator.DefineLabel();
Label L_0526 = getGenerator.DefineLabel();
Label L_054e = getGenerator.DefineLabel();

ArrayList getLabelArr = new ArrayList();
for (int i = 0; i < infos.Length; i++)
{
try
{
MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 0) continue; //忽略索引器

getLabelArr.Add(getGenerator.DefineLabel());
}
catch { }
}
Label[] getLabels = new Label[getLabelArr.Count];
getLabelArr.CopyTo(getLabels);

getGenerator.Emit(OpCodes.Volatile);
getGenerator.Emit(OpCodes.Ldsfld, getHashtableBuilder);
getGenerator.Emit(OpCodes.Brtrue, L_0112);
getGenerator.Emit(OpCodes.Ldc_I4, infos.Length);
getGenerator.Emit(OpCodes.Ldc_R4, .5F);
getGenerator.Emit(OpCodes.Newobj, typeof(Hashtable).GetConstructor(new Type[] { typeof(Int32), typeof(Single) }));
for (int i = 0, j = 0; i < infos.Length; i++)
{
try
{
MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 0) continue;
getGenerator.Emit(OpCodes.Dup);
getGenerator.Emit(OpCodes.Ldstr, infos[i].Name);
getGenerator.Emit(OpCodes.Ldc_I4_S, j++);
getGenerator.Emit(OpCodes.Box, typeof(Int32));
getGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("Add", new Type[] { typeof(object), typeof(object) }));
}
catch { }
}
getGenerator.Emit(OpCodes.Volatile);
getGenerator.Emit(OpCodes.Stsfld, getHashtableBuilder);
getGenerator.MarkLabel(L_0112);
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Dup);
getGenerator.Emit(OpCodes.Stloc_1);
getGenerator.Emit(OpCodes.Brfalse, L_0256);
getGenerator.Emit(OpCodes.Volatile);
getGenerator.Emit(OpCodes.Ldsfld, getHashtableBuilder); // [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000022-1
getGenerator.Emit(OpCodes.Ldloc_1);
getGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("get_Item", new Type[] { typeof(object) }));
getGenerator.Emit(OpCodes.Dup);
getGenerator.Emit(OpCodes.Stloc_1);
getGenerator.Emit(OpCodes.Brfalse, L_0256);
getGenerator.Emit(OpCodes.Ldloc_1);
getGenerator.Emit(OpCodes.Unbox, typeof(Int32));
getGenerator.Emit(OpCodes.Ldind_I4);
getGenerator.Emit(OpCodes.Switch, getLabels);
getGenerator.Emit(OpCodes.Br, L_0256);

for (int i = 0, j = 0; i < infos.Length; i++)
{
try
{
MethodInfo minfo = type.GetMethod("get_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 0) continue;
getGenerator.MarkLabel(getLabels[j++]);
getGenerator.Emit(OpCodes.Ldarg_1);
getGenerator.Emit(OpCodes.Castclass, type);
getGenerator.Emit(OpCodes.Callvirt, minfo);
if (infos[i].PropertyType.IsValueType)
getGenerator.Emit(OpCodes.Box, infos[i].PropertyType);
getGenerator.Emit(OpCodes.Stloc_0);
getGenerator.Emit(OpCodes.Br, getRet);
}
catch { }
}

getGenerator.MarkLabel(L_0256);
if (type.BaseType == typeof(Array))
{
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Ldc_I4_0);
getGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
getGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
getGenerator.Emit(OpCodes.Brfalse_S, L_0526);
getGenerator.Emit(OpCodes.Ldarg_1);
getGenerator.Emit(OpCodes.Castclass, typeof(object[]));
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
getGenerator.Emit(OpCodes.Ldelem_Ref);
getGenerator.Emit(OpCodes.Stloc_0);
getGenerator.Emit(OpCodes.Br_S, getRet);
getGenerator.MarkLabel(L_0526);
}
else
{
MethodInfo intIndexer = type.GetMethod("get_Item", new Type[] { typeof(Int32) });
//if index is object type, GetMethod will return indexer's MethodInfo whatever type I pass
if (intIndexer != null && intIndexer.GetParameters()[0].ParameterType != typeof(object))
{
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Ldc_I4_0);
getGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
getGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
getGenerator.Emit(OpCodes.Brfalse_S, L_0526);
getGenerator.Emit(OpCodes.Ldarg_1);
getGenerator.Emit(OpCodes.Castclass, type);
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
getGenerator.Emit(OpCodes.Callvirt, intIndexer);
getGenerator.Emit(OpCodes.Stloc_0);
getGenerator.Emit(OpCodes.Br_S, getRet);
getGenerator.MarkLabel(L_0526);
}

MethodInfo strIndexer = type.GetMethod("get_Item", new Type[] { typeof(string) });
if (strIndexer != null)
{
getGenerator.Emit(OpCodes.Ldarg_1);
getGenerator.Emit(OpCodes.Castclass, type);
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Callvirt, strIndexer);
getGenerator.Emit(OpCodes.Stloc_0);
getGenerator.Emit(OpCodes.Br_S, getRet);
getGenerator.MarkLabel(L_054e);
}
}

getGenerator.Emit(OpCodes.Ldstr, "The property named ");
getGenerator.Emit(OpCodes.Ldarg_2);
getGenerator.Emit(OpCodes.Ldstr, " does not exists");
getGenerator.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) }));
getGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
getGenerator.Emit(OpCodes.Throw);

getGenerator.MarkLabel(getRet);
getGenerator.Emit(OpCodes.Ldloc_0);
getGenerator.Emit(OpCodes.Ret);

#endregion

#region Set

MethodBuilder setMethodBuilder = typeBuilder.DefineMethod(
"SetValue", MethodAttributes.Public | MethodAttributes.Virtual, null
, new Type[] { typeof(object), typeof(string), typeof(object) });
ILGenerator setGenerator = setMethodBuilder.GetILGenerator();
setGenerator.DeclareLocal(typeof(object));

Label L_0220 = setGenerator.DefineLabel();
Label L_053b = setGenerator.DefineLabel();
Label L_0568 = setGenerator.DefineLabel();
Label L_0593 = setGenerator.DefineLabel();
Label setRet = setGenerator.DefineLabel();

ArrayList setLabelList = new ArrayList();
for (int i = 0; i < infos.Length; i++)
{
try
{
MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 1) continue;
setLabelList.Add(setGenerator.DefineLabel());
}
catch { }
}
Label[] setLabels = new Label[setLabelList.Count];
setLabelList.CopyTo(setLabels);

setGenerator.Emit(OpCodes.Volatile);
setGenerator.Emit(OpCodes.Ldsfld, setHashtableBuilder);
setGenerator.Emit(OpCodes.Brtrue, L_0220);
setGenerator.Emit(OpCodes.Ldc_I4, infos.Length);
setGenerator.Emit(OpCodes.Ldc_R4, 1F);
setGenerator.Emit(OpCodes.Newobj, typeof(Hashtable).GetConstructor(new Type[] { typeof(Int32), typeof(Single) }));
for (int i = 0, j = 0; i < infos.Length; i++)
{
MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 1) continue;
setGenerator.Emit(OpCodes.Dup);
setGenerator.Emit(OpCodes.Ldstr, infos[i].Name);
setGenerator.Emit(OpCodes.Ldc_I4_S, j++);
setGenerator.Emit(OpCodes.Box, typeof(Int32));
setGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("Add", new Type[] { typeof(object), typeof(object) }));
}
setGenerator.Emit(OpCodes.Volatile);
setGenerator.Emit(OpCodes.Stsfld, setHashtableBuilder);

setGenerator.MarkLabel(L_0220);
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Dup);
setGenerator.Emit(OpCodes.Stloc_0);
setGenerator.Emit(OpCodes.Brfalse, L_053b);
setGenerator.Emit(OpCodes.Volatile);
setGenerator.Emit(OpCodes.Ldsfld, setHashtableBuilder); // [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000022-1
setGenerator.Emit(OpCodes.Ldloc_0);
setGenerator.Emit(OpCodes.Call, typeof(Hashtable).GetMethod("get_Item", new Type[] { typeof(object) }));
setGenerator.Emit(OpCodes.Dup);
setGenerator.Emit(OpCodes.Stloc_0);
setGenerator.Emit(OpCodes.Brfalse, L_053b);
setGenerator.Emit(OpCodes.Ldloc_0);
setGenerator.Emit(OpCodes.Unbox, typeof(Int32));
setGenerator.Emit(OpCodes.Ldind_I4);
setGenerator.Emit(OpCodes.Switch, setLabels);
setGenerator.Emit(OpCodes.Br, L_053b);

for (int i = 0, j = 0; i < infos.Length; i++)
{
MethodInfo minfo = type.GetMethod("set_" + infos[i].Name);
if (minfo == null || minfo.GetParameters().Length > 1) continue;
setGenerator.MarkLabel(setLabels[j++]);
setGenerator.Emit(OpCodes.Ldarg_1);
setGenerator.Emit(OpCodes.Castclass, type); // NoReflection.TestClass
setGenerator.Emit(OpCodes.Ldarg_3);
if (infos[i].PropertyType.IsValueType)
{
setGenerator.Emit(OpCodes.Unbox, infos[i].PropertyType);
if (infos[i].PropertyType == typeof(Int64))
setGenerator.Emit(OpCodes.Ldind_I8);
if (infos[i].PropertyType == typeof(Int32))
setGenerator.Emit(OpCodes.Ldind_I4);
if (infos[i].PropertyType == typeof(Int16))
setGenerator.Emit(OpCodes.Ldind_I2);
if (infos[i].PropertyType == typeof(Byte))
setGenerator.Emit(OpCodes.Ldind_U1);
if (infos[i].PropertyType == typeof(SByte))
setGenerator.Emit(OpCodes.Ldind_I1);
if (infos[i].PropertyType == typeof(Boolean))
setGenerator.Emit(OpCodes.Ldind_I1);
if (infos[i].PropertyType == typeof(UInt64))
setGenerator.Emit(OpCodes.Ldind_I8);
if (infos[i].PropertyType == typeof(UInt32))
setGenerator.Emit(OpCodes.Ldind_U4);
if (infos[i].PropertyType == typeof(UInt16))
setGenerator.Emit(OpCodes.Ldind_U2);
if (infos[i].PropertyType == typeof(float))
setGenerator.Emit(OpCodes.Conv_R4);
if (infos[i].PropertyType == typeof(Decimal))
setGenerator.Emit(OpCodes.Ldobj, typeof(Decimal));
if (infos[i].PropertyType == typeof(DateTime))
setGenerator.Emit(OpCodes.Ldobj, typeof(DateTime));

}
else
{
setGenerator.Emit(OpCodes.Castclass, infos[i].PropertyType); // NoReflection.TestClass
}
setGenerator.Emit(OpCodes.Callvirt, minfo);
setGenerator.Emit(OpCodes.Br, setRet);

}

setGenerator.MarkLabel(L_053b);
if (type.BaseType == typeof(Array))
{
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Ldc_I4_0);
setGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
setGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
setGenerator.Emit(OpCodes.Brfalse_S, L_0568);
setGenerator.Emit(OpCodes.Ldarg_1);
setGenerator.Emit(OpCodes.Castclass, typeof(object[]));
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
setGenerator.Emit(OpCodes.Ldarg_3);
setGenerator.Emit(OpCodes.Stelem_Ref);
setGenerator.MarkLabel(L_0568);
setGenerator.Emit(OpCodes.Br, setRet);
}
else
{
PropertyInfo testInfo;
testInfo = type.GetProperty("Item", new Type[] { typeof(Int32) });
if (testInfo != null)
{
MethodInfo intSetIndexer = type.GetMethod("set_Item", new Type[] { typeof(Int32), testInfo.PropertyType });
if (intSetIndexer != null && intSetIndexer.GetParameters()[0].ParameterType != typeof(object))
{
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Ldc_I4_0);
setGenerator.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new Type[] { typeof(Int32) }));
setGenerator.Emit(OpCodes.Call, typeof(Char).GetMethod("IsDigit", new Type[] { typeof(Char) }));
setGenerator.Emit(OpCodes.Brfalse_S, L_0568);
setGenerator.Emit(OpCodes.Ldarg_1);
setGenerator.Emit(OpCodes.Castclass, type);
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) }));
setGenerator.Emit(OpCodes.Ldarg_3);
setGenerator.Emit(OpCodes.Castclass, typeof(string));
setGenerator.Emit(OpCodes.Callvirt, intSetIndexer);
setGenerator.Emit(OpCodes.Br, setRet);
setGenerator.MarkLabel(L_0568);
}
}
testInfo = type.GetProperty("Item", new Type[] { typeof(String) });
if (testInfo != null)
{
MethodInfo strSetIndexer = type.GetMethod("set_Item", new Type[] { typeof(string), testInfo.PropertyType });
if (strSetIndexer != null)
{

setGenerator.Emit(OpCodes.Ldarg_1);
setGenerator.Emit(OpCodes.Castclass, type);
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Ldarg_3);
if (testInfo.PropertyType.IsValueType)
{
setGenerator.Emit(OpCodes.Unbox, testInfo.PropertyType);
if (testInfo.PropertyType == typeof(Int64))
setGenerator.Emit(OpCodes.Ldind_I8);
if (testInfo.PropertyType == typeof(Int32))
setGenerator.Emit(OpCodes.Ldind_I4);
if (testInfo.PropertyType == typeof(Int16))
setGenerator.Emit(OpCodes.Ldind_I2);
if (testInfo.PropertyType == typeof(Byte))
setGenerator.Emit(OpCodes.Ldind_U1);
if (testInfo.PropertyType == typeof(SByte))
setGenerator.Emit(OpCodes.Ldind_I1);
if (testInfo.PropertyType == typeof(Boolean))
setGenerator.Emit(OpCodes.Ldind_I1);
if (testInfo.PropertyType == typeof(UInt64))
setGenerator.Emit(OpCodes.Ldind_I8);
if (testInfo.PropertyType == typeof(UInt32))
setGenerator.Emit(OpCodes.Ldind_U4);
if (testInfo.PropertyType == typeof(UInt16))
setGenerator.Emit(OpCodes.Ldind_U2);
if (testInfo.PropertyType == typeof(Decimal))
setGenerator.Emit(OpCodes.Ldobj, typeof(Decimal));
if (testInfo.PropertyType == typeof(DateTime))
setGenerator.Emit(OpCodes.Ldobj, typeof(DateTime));
}
else
{
setGenerator.Emit(OpCodes.Castclass, testInfo.PropertyType);
}

setGenerator.Emit(OpCodes.Callvirt, strSetIndexer);
setGenerator.Emit(OpCodes.Br, setRet);
setGenerator.MarkLabel(L_0593);
}
}
}
setGenerator.Emit(OpCodes.Ldstr, "The property named ");
setGenerator.Emit(OpCodes.Ldarg_2);
setGenerator.Emit(OpCodes.Ldstr, " does not exists");
setGenerator.Emit(OpCodes.Call, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) }));
setGenerator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
setGenerator.Emit(OpCodes.Throw);
setGenerator.MarkLabel(setRet);
setGenerator.Emit(OpCodes.Ret);

#endregion
Type t = typeBuilder.CreateType();
//assyBuilder.Save("ValueHandler." + type.FullName + ".dll");
IValueHandler result = Activator.CreateInstance(t) as IValueHandler;
handlers.Add(type, result);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: