如何获取 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;
    }

我的目标是从具有基础类型 MyClassIMyClass 开始,它同时具有 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;
}