[英]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.