簡體   English   中英

運行時類型的泛型類

[英]Generics class from a runtime type

我有一個在運行時建立的類(RClass),也有一個通用類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);  
        }
    }
}
}

簡而言之,你不能:-)

有多種可能的解決方案:

  • 非通用接口:

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

    例如,這是通過IEnumerable / IEnumerable<T>完成的

  • dynamic

     dynamic gs = Activator.CreateInstance(dta); 
  • 您將對象傳遞給一個類,該類將使用反射來“探索”它(例如,通常是DataGrid

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

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

    然后通過反射調用Work<GType>()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM