如何获取 Reflection.Emit 类型的实例?
How to get an instance of a Reflection.Emit type?
所以我有一个 class:
public class MyClass : IMyClass
{
public string foo {get;}
public MyClass bar {get;}
}
还有一个界面:
public interface IMyClass
{
string foo {get;}
}
以及创建发射类型的系统:
private static Type MakeDynamicType<T>() where T : class
{
var myType = GetTypeBuilder();
myType.AddInterfaceImplementation(typeof(T));
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
AddProperty(myType, property, typeof(T));
AddCtor(myType, typeof(T));
return myType.CreateType();
}
private static void AddCtor(TypeBuilder myType, Type inputParamType)
{
var myCtor = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
var ilGenerator = myCtor.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);
}
private const MethodAttributes GET_SET_ATTR = MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig | MethodAttributes.Virtual;
private static void AddProperty(TypeBuilder myType, PropertyInfo property, Type interfaceType)
{
var myField = myType.DefineField($"m_{property.Name}", property.PropertyType, FieldAttributes.Private);
var myProperty = myType.DefineProperty(property.Name, PropertyAttributes.HasDefault, property.PropertyType,
parameterTypes: null);
var interfaceGetMethod = interfaceType.GetMethod($"get_{property.Name}");
if (interfaceGetMethod != null)
AddGetter(myType, property, myField, myProperty, interfaceGetMethod);
var interfaceSetMethod = interfaceType.GetMethod($"set_{property.Name}");
if (interfaceSetMethod != null)
AddSetter(myType, property, myField, myProperty, interfaceSetMethod);
}
private static void AddGetter(TypeBuilder myType, PropertyInfo property, FieldInfo myField,
PropertyBuilder myProperty, MethodInfo interfaceGetMethod)
{
var myGet = myType.DefineMethod($"get_{property.Name}", GET_SET_ATTR, property.PropertyType,
Type.EmptyTypes);
var getIl = myGet.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, myField);
getIl.Emit(OpCodes.Ret);
myProperty.SetGetMethod(myGet);
myType.DefineMethodOverride(myGet, interfaceGetMethod);
}
private static void AddSetter(TypeBuilder myType, PropertyInfo property, FieldInfo myField,
PropertyBuilder myProperty, MethodInfo interfaceSetMethod)
{
var mySet = myType.DefineMethod($"set_{property.Name}", GET_SET_ATTR, returnType: null,
new[] { property.PropertyType });
var setIl = mySet.GetILGenerator();
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, myField);
setIl.Emit(OpCodes.Ret);
myProperty.SetSetMethod(mySet);
myType.DefineMethodOverride(mySet, interfaceSetMethod);
}
private static TypeBuilder GetTypeBuilder()
{
var myDomain = Thread.GetDomain();
var myAsmName = new AssemblyName("MyDynamicAssembly");
var myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);
var myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");
return myModBuilder.DefineType("MyDynamicType", TypeAttributes.Public);
}
那么现在如何从 IMyClass 类型引用到 MyClass 对象创建我的反射类型的实例?
public static IEnumerable<T> ToInterfacedObjects<T>(this IEnumerable<T> data) where T : class
{
var myType = MakeDynamicType<T>();
var list = new List<T>();
foreach (var datum in data)
{
list.Add((T)myType.GetValue(datum));//What do I write for GetValue??
}
return list;
}
我的目标是从具有基础类型 MyClass
的 IMyClass
开始,它同时具有 foo 和 bar,并以具有基础类型的 IMyClass
结束发射类型的,它有 foo
但没有 bar
.
如果您有 MakeDynamicType<T>
的实现,并假设您的界面只有简单的 {get; set;}
属性,那么这不会像这样简单:
public static IList<T> ToInterfacedObjects<T>(this IEnumerable<T> data) where T : class
{
var myType = MakeDynamicType<T>();
var list = new List<T>();
foreach (var datum in data)
{
var obj = (T)Activator.CreateInstance(myType);
foreach (var pi in typeof(T).GetProperties())
{
var val = pi.GetValue(datum);
pi.SetValue(obj, val);
}
list.Add(obj);
}
return list;
}
所以我有一个 class:
public class MyClass : IMyClass
{
public string foo {get;}
public MyClass bar {get;}
}
还有一个界面:
public interface IMyClass
{
string foo {get;}
}
以及创建发射类型的系统:
private static Type MakeDynamicType<T>() where T : class
{
var myType = GetTypeBuilder();
myType.AddInterfaceImplementation(typeof(T));
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
AddProperty(myType, property, typeof(T));
AddCtor(myType, typeof(T));
return myType.CreateType();
}
private static void AddCtor(TypeBuilder myType, Type inputParamType)
{
var myCtor = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
var ilGenerator = myCtor.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);
}
private const MethodAttributes GET_SET_ATTR = MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig | MethodAttributes.Virtual;
private static void AddProperty(TypeBuilder myType, PropertyInfo property, Type interfaceType)
{
var myField = myType.DefineField($"m_{property.Name}", property.PropertyType, FieldAttributes.Private);
var myProperty = myType.DefineProperty(property.Name, PropertyAttributes.HasDefault, property.PropertyType,
parameterTypes: null);
var interfaceGetMethod = interfaceType.GetMethod($"get_{property.Name}");
if (interfaceGetMethod != null)
AddGetter(myType, property, myField, myProperty, interfaceGetMethod);
var interfaceSetMethod = interfaceType.GetMethod($"set_{property.Name}");
if (interfaceSetMethod != null)
AddSetter(myType, property, myField, myProperty, interfaceSetMethod);
}
private static void AddGetter(TypeBuilder myType, PropertyInfo property, FieldInfo myField,
PropertyBuilder myProperty, MethodInfo interfaceGetMethod)
{
var myGet = myType.DefineMethod($"get_{property.Name}", GET_SET_ATTR, property.PropertyType,
Type.EmptyTypes);
var getIl = myGet.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, myField);
getIl.Emit(OpCodes.Ret);
myProperty.SetGetMethod(myGet);
myType.DefineMethodOverride(myGet, interfaceGetMethod);
}
private static void AddSetter(TypeBuilder myType, PropertyInfo property, FieldInfo myField,
PropertyBuilder myProperty, MethodInfo interfaceSetMethod)
{
var mySet = myType.DefineMethod($"set_{property.Name}", GET_SET_ATTR, returnType: null,
new[] { property.PropertyType });
var setIl = mySet.GetILGenerator();
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, myField);
setIl.Emit(OpCodes.Ret);
myProperty.SetSetMethod(mySet);
myType.DefineMethodOverride(mySet, interfaceSetMethod);
}
private static TypeBuilder GetTypeBuilder()
{
var myDomain = Thread.GetDomain();
var myAsmName = new AssemblyName("MyDynamicAssembly");
var myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);
var myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");
return myModBuilder.DefineType("MyDynamicType", TypeAttributes.Public);
}
那么现在如何从 IMyClass 类型引用到 MyClass 对象创建我的反射类型的实例?
public static IEnumerable<T> ToInterfacedObjects<T>(this IEnumerable<T> data) where T : class
{
var myType = MakeDynamicType<T>();
var list = new List<T>();
foreach (var datum in data)
{
list.Add((T)myType.GetValue(datum));//What do I write for GetValue??
}
return list;
}
我的目标是从具有基础类型 MyClass
的 IMyClass
开始,它同时具有 foo 和 bar,并以具有基础类型的 IMyClass
结束发射类型的,它有 foo
但没有 bar
.
如果您有 MakeDynamicType<T>
的实现,并假设您的界面只有简单的 {get; set;}
属性,那么这不会像这样简单:
public static IList<T> ToInterfacedObjects<T>(this IEnumerable<T> data) where T : class
{
var myType = MakeDynamicType<T>();
var list = new List<T>();
foreach (var datum in data)
{
var obj = (T)Activator.CreateInstance(myType);
foreach (var pi in typeof(T).GetProperties())
{
var val = pi.GetValue(datum);
pi.SetValue(obj, val);
}
list.Add(obj);
}
return list;
}