来自运行时类型的泛型类

时间:2015-05-16 18:30:00

标签: c# reflection reflection.emit

我有一个在运行时构建的类(RClass)并且还有一个Generic类B,我如何创建一种DataLoader并使用它的方法。

public interface IDataLoader<GType>
{
//some code
   GType SampleMethod();
}

public class DataLoader <GType>: IDataLoader<GType>
{
  GType SampleMethod(){
    //some code
  }
}

//class "RClass" created in runtime
MyClassBuilder MCB=new MyClassBuilder("RClass");
var myclass = MCB.CreateObject(new string[3] { "id", "name", "link" }, new Type[3] { typeof(int), typeof(string), typeof(string) });
Type myclassType = myclass.GetType();

var dta = typeof(DataLoader<>).MakeGenericType(myclassType);
// ?????
var gs = (???)Activator.CreateInstance(dta);
gs.SampleMethod();

对于在运行时构建类,我使用本文http://www.codeproject.com/Articles/13337/Introduction-to-Creating-Dynamic-Types-with-Reflec

MyClassBuilder的全部细节是

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using Faroid;

namespace Faroid
{
    namespace Runtime
    {
    public class ORMapperFactory  
    {  
        string asmName;
        AssemblyName assemblyName;
        AssemblyBuilder asmBuilder;
        ModuleBuilder modBuilder;

        public ORMapperFactory(string ClassName)  
        {  
            asmName = ClassName;  
        }

        void GenerateAssemblyAndModule()
        {
            if (asmBuilder == null)
            {
                assemblyName = new AssemblyName();
                assemblyName.Name = asmName;
                AppDomain thisDomain = Thread.GetDomain();
                asmBuilder = thisDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

                modBuilder = asmBuilder.DefineDynamicModule(asmBuilder.GetName().Name, false);
            }
        }

        TypeBuilder CreateType(ModuleBuilder moduleBuilder, string typeName)
        {
            TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, 
                TypeAttributes.Public | 
                TypeAttributes.Class |
                TypeAttributes.AutoClass | 
                TypeAttributes.AnsiClass | 
                TypeAttributes.BeforeFieldInit | 
                TypeAttributes.AutoLayout, 
                typeof(object), 
                new Type[] {typeof(IORMapper)});

            return typeBuilder;
        }

        public IORMapper CreateObject(string[] PropertyNames,Type[]Types, bool returnAdapter)  
        {  
            if(PropertyNames.Length!=Types.Length)  
            {  
                Console.WriteLine("The number of property names should match their corresopnding types number");  
            }  

            TypeBuilder DynamicClass = CreateClass ();  
            CreateConstructor (DynamicClass);
            for (int ind = 0; ind < PropertyNames.Count (); ind++) {
                CreateProperty (DynamicClass, PropertyNames [ind], Types [ind]);
                //cache adapter instance
            //  adapters.Add(dt.TableName, dra);
            }

            Type type = DynamicClass.CreateType();  

            //Create an instance of the DataRowAdapter
            var dra = (IORMapper)Activator.CreateInstance(type, true);

            //cache adapter instance
            //adapters.Add(dt.TableName, dra);

            //if just initializing adapter, dont return instance
            return !returnAdapter ? null : dra;

        }

        TypeBuilder CreateClass()  
        { 
            GenerateAssemblyAndModule ();
            TypeBuilder typeBuilder = CreateType (modBuilder, assemblyName.FullName);
            return typeBuilder;  
        }

        void CreateConstructor(TypeBuilder typeBuilder)
        {
            ConstructorBuilder constructor = typeBuilder.DefineConstructor(
                MethodAttributes.Public | 
                MethodAttributes.SpecialName | 
                MethodAttributes.RTSpecialName, 
                CallingConventions.Standard, 
                new Type[0]);
            //Define the reflection ConstructorInfor for System.Object
            ConstructorInfo conObj = typeof(object).GetConstructor(new Type[0]);

            //call constructor of base object
            ILGenerator il = constructor.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, conObj);
            il.Emit(OpCodes.Ret);
        }

//      static void CreateConstructor(TypeBuilder typeBuilder)  
//      {  
//          typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);  
//      }

        void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)  
        {
            FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);  

            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);  
            MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, 
                MethodAttributes.Public | 
                MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig, 
                propertyType, Type.EmptyTypes);

            ILGenerator getIl = getPropMthdBldr.GetILGenerator();  

            getIl.Emit(OpCodes.Ldarg_0);  
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);  
            getIl.Emit(OpCodes.Ret);  

            MethodBuilder setPropMthdBldr =typeBuilder.DefineMethod("set_" + propertyName,  
                MethodAttributes.Public |  
                MethodAttributes.SpecialName |  
                MethodAttributes.HideBySig,  
                null, new[] { propertyType });  

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();  
            Label modifyProperty = setIl.DefineLabel();  
            Label exitSet = setIl.DefineLabel();  

            setIl.MarkLabel(modifyProperty);  
            setIl.Emit(OpCodes.Ldarg_0);  
            setIl.Emit(OpCodes.Ldarg_1);  
            setIl.Emit(OpCodes.Stfld, fieldBuilder);  

            setIl.Emit(OpCodes.Nop);  
            setIl.MarkLabel(exitSet);  
            setIl.Emit(OpCodes.Ret);  

            propertyBuilder.SetGetMethod(getPropMthdBldr);  
            propertyBuilder.SetSetMethod(setPropMthdBldr);  
        }
    }
}
}

1 个答案:

答案 0 :(得分:1)

简单地说,你不能: - )

有各种可能的解决方案:

  • 非通用界面:

    public interface IDataLoader
    {
    //some code
       object SampleMethod();
    }
    

    这是由IEnumerable / IEnumerable<T>完成的,例如

  • dynamic

    dynamic gs = Activator.CreateInstance(dta);
    
  • 您将对象传递给将使用反射到&#34;探索&#34;的类。它(例如DataGrid s),例如

  • 您可以在通用方法中包含您想要做的所有事情:

    public void Work<GType>(IDataLoader<GType> dataLoader)
    {
        // Here you can work with the IDataLoader<GType>
    }
    

    然后通过反思调用Work<GType>()