2015-05-16 3 views
0

У меня есть класс, который создается во время выполнения (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); 
     } 
    } 
} 
} 
+0

Что такое полный тип 'MyClassBuilder'? –

+0

деталь MyClassBuilder - это сообщение о начале работы – eager

+0

Поскольку 'dta' - это тип выполнения, объект' gs' этого типа также имеет тип выполнения (очевидно). И вы не можете статически вызывать метод типа, который известен только во время выполнения. Поэтому вам нужно вызвать 'SampleMethod' с помощью отражения (т. Е. Что-то вроде' dta.GetMethod ("SampleMethod"). Invoke (gs, null) '). – poke

ответ

1

Проще говоря, вы не можете :-)

Есть различные возможные решения:

  • не-общий интерфейс:

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

    это делается IEnumerable/IEnumerable<T>, например

  • dynamic

    dynamic gs = Activator.CreateInstance(dta); 
    
  • Вы передаете объект класса, который будет использовать отражение «изучить» его (DataGrid s в целом, например)

  • Вы заключите все, что вы хотите сделать, в общем методе:

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

    , а затем через отражение вы называете Work<GType>()

+0

@svick Спасибо, я не смог отформатировать его правильно :-) – xanatos

+0

спасибо @xanatos, я использую не-общий интерфейс и его работу! объект myreturned = gs.SampleMethod(); как я могу получить runty GType из объекта retarned? – eager

+0

@NaderSediq Дело в том, что вы не можете ... Это всегда один и тот же ответ: у вас есть 4 способа его иметь :-) У вас может быть интерфейс IType, использование динамического ... Вы не можете полностью создать новые типы объектов динамически, а затем их статически ставить. – xanatos

Смежные вопросы