在.net中的代码中创建类类型# [英] Create a class type in code in .net c#

查看:151
本文介绍了在.net中的代码中创建类类型#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我寻找System.Linq.Expression功能(在代码中创建表达式树,编译它们,执行它们)时,我问自己,如果这是可能的类创建,特别是泛型类。



我会期望像Expression.Class()或Expression.GenericClass()。看看方法我没有看到任何这些。这将是非常实用的,因为我可以动态构建业务对象 - 即时。其实这是我需要的。

解决方案

有一个例子说明如何使用.net c#在All-In-One Framework codeplex项目中执行此操作
http://1code.codeplex.com/

  //定义程序集和模块。 

AppDomain appDomain = AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName(EmittedAssembly);
AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(
assemblyName,AssemblyBuilderAccess.RunAndSave);

//程序集由可执行模块组成。对于单模块
//程序集,模块名称和文件名与
//程序集名称相同。

ModuleBuilder module = assembly.DefineDynamicModule(
assemblyName.Name,assemblyName.Name +.dll);


//////////////////////////////////////// ///////////////////////////////
//声明类型(类)。
//

//声明类ClassA
TypeBuilder classA = module.DefineType(ClassA,TypeAttributes.Public);
//声明类ClassB
TypeBuilder classB = module.DefineType(ClassB,TypeAttributes.Public);

//定义字段stringField,classBField
FieldBuilder stringField = classA.DefineField(stringField,
typeof(string),FieldAttributes.Private);
FieldBuilder classBField = classA.DefineField(classBField,
classB,FieldAttributes.Public);

////////////////////////////////////////// ///////////////////////////
//定义属性ClassBProperty
PropertyBuilder classBProperty = classA.DefineProperty(
ClassBProperty,PropertyAttributes.None,classB,null);

//属性集& get方法的特殊属性集
MethodAttributes getSetAttr = MethodAttributes.Public |
MethodAttributes.SpecialName | MethodAttributes.HideBySig;

//为ClassBProperty定义get访问器方法
MethodBuilder classBGetProp = classA.DefineMethod(
get_ClassBProperty,getSetAttr,classB,Type.EmptyTypes);
ILGenerator classBGetIL = classBGetProp.GetILGenerator();
classBGetIL.Emit(OpCodes.Ldarg_0);
classBGetIL.Emit(OpCodes.Ldfld,classBField);
classBGetIL.Emit(OpCodes.Ret);

//为ClassBProperty定义访问器方法
MethodBuilder classBSetProp = classA.DefineMethod(
set_ClassBProperty,getSetAttr,null,new Type [] {classB}) ;
ILGenerator sampleSetIL = classBSetProp.GetILGenerator();
sampleSetIL.Emit(OpCodes.Ldarg_0);
sampleSetIL.Emit(OpCodes.Ldarg_1);
sampleSetIL.Emit(OpCodes.Stfld,classBField);
sampleSetIL.Emit(OpCodes.Ret);

//将get& set方法映射到PropertyBuilder
classBProperty.SetGetMethod(classBGetProp);
classBProperty.SetSetMethod(classBSetProp);

////////////////////////////////////////// ///////////////////////////
//定义一个使用classBField的方法
MethodBuilder classAMethod = classA.DefineMethod (ClassAMethod,
MethodAttributes.Public);

//定义列表泛型和ienumerable泛型
类型listOf = typeof(List<>);
Type enumOf = typeof(IEnumerable<>);
类型listOfClassA = listOf.MakeGenericType(classA);
类型enumOfClassA = enumOf.MakeGenericType(classA);

//为ClassB定义方法ClassBMethod
MethodBuilder classBMethod = classB.DefineMethod(ClassBMethod,
MethodAttributes.Public,typeof(void),new Type [] {listOfClassA});
classBMethod.DefineParameter(1,ParameterAttributes.None,list);

//写入调用ClassBMethod的ClassAMethod的主体
ILGenerator ilgenA = classAMethod.GetILGenerator();
ilgenA.Emit(OpCodes.Nop);
ilgenA.Emit(OpCodes.Ldarg_0);
ilgenA.Emit(OpCodes.Ldfld,classBField);
ilgenA.Emit(OpCodes.Ldnull);
ilgenA.Emit(OpCodes.Callvirt,classBMethod);
ilgenA.Emit(OpCodes.Ret);

////////////////////////////////////////// ///////////////////////////
//创建类型。
//

classA.CreateType();
classB.CreateType();

////////////////////////////////////////// ///////////////////////////
//保存程序集。
//

assembly.Save(assemblyName.Name +.dll);对不起,这有点长..:-P

When I was looking to the System.Linq.Expression capabilities (creating expression trees in code, compiling them, executing them) I was asking myself if this is possible for class creation as well - specifically generic classes.

I would expect something like Expression.Class() or Expression.GenericClass(). Looking at the methods I did not see any of those. It would be very practical, since I could build business objects dynamically - on the fly. Actually that is what I need. If there is another approach to that in .net c# that is also of interest to me.

解决方案

There is an example of how to do this in All-In-One Framework codeplex project http://1code.codeplex.com/

// Define the assembly and the module.

AppDomain appDomain = AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName("EmittedAssembly");
AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.RunAndSave);

// An assembly is made up of executable modules. For a single-module
// assembly, the module name and file name are the same as the 
// assembly name. 

ModuleBuilder module = assembly.DefineDynamicModule(
assemblyName.Name, assemblyName.Name + ".dll");


/////////////////////////////////////////////////////////////////////
// Declare the types (classes).
// 

// Declare the class "ClassA"
TypeBuilder classA = module.DefineType("ClassA", TypeAttributes.Public);
// Declare the class "ClassB"
TypeBuilder classB = module.DefineType("ClassB", TypeAttributes.Public);

// Define the fields stringField, classBField
FieldBuilder stringField = classA.DefineField("stringField",
typeof(string), FieldAttributes.Private);
FieldBuilder classBField = classA.DefineField("classBField",
classB, FieldAttributes.Public);

/////////////////////////////////////////////////////////////////////
// Define the property ClassBProperty
PropertyBuilder classBProperty = classA.DefineProperty(
    "ClassBProperty", PropertyAttributes.None, classB, null);

// The special set of attributes for the property set&get methods
MethodAttributes getSetAttr = MethodAttributes.Public |
    MethodAttributes.SpecialName | MethodAttributes.HideBySig;

// Define the "get" accessor method for ClassBProperty
MethodBuilder classBGetProp = classA.DefineMethod(
    "get_ClassBProperty", getSetAttr, classB, Type.EmptyTypes);
ILGenerator classBGetIL = classBGetProp.GetILGenerator();
classBGetIL.Emit(OpCodes.Ldarg_0);
classBGetIL.Emit(OpCodes.Ldfld, classBField);
classBGetIL.Emit(OpCodes.Ret);

// Define the "set" accessor method for ClassBProperty
MethodBuilder classBSetProp = classA.DefineMethod(
    "set_ClassBProperty", getSetAttr, null, new Type[] { classB });
ILGenerator sampleSetIL = classBSetProp.GetILGenerator();
sampleSetIL.Emit(OpCodes.Ldarg_0);
sampleSetIL.Emit(OpCodes.Ldarg_1);
sampleSetIL.Emit(OpCodes.Stfld, classBField);
sampleSetIL.Emit(OpCodes.Ret);

// Map the get&set methods to PropertyBuilder
classBProperty.SetGetMethod(classBGetProp);
classBProperty.SetSetMethod(classBSetProp);

/////////////////////////////////////////////////////////////////////
// Define a method that uses the classBField
MethodBuilder classAMethod = classA.DefineMethod("ClassAMethod", 
    MethodAttributes.Public);

// Define the list generics and ienumerable generic
Type listOf = typeof(List<>);
Type enumOf = typeof(IEnumerable<>);
Type listOfClassA = listOf.MakeGenericType(classA);
Type enumOfClassA = enumOf.MakeGenericType(classA);

// Define the method, ClassBMethod, for ClassB
MethodBuilder classBMethod = classB.DefineMethod("ClassBMethod", 
    MethodAttributes.Public, typeof(void), new Type[] { listOfClassA });
classBMethod.DefineParameter(1, ParameterAttributes.None, "list");

// Write the body of ClassAMethod that calls ClassBMethod
ILGenerator ilgenA = classAMethod.GetILGenerator();
ilgenA.Emit(OpCodes.Nop);
ilgenA.Emit(OpCodes.Ldarg_0);
ilgenA.Emit(OpCodes.Ldfld, classBField);
ilgenA.Emit(OpCodes.Ldnull);
ilgenA.Emit(OpCodes.Callvirt, classBMethod);
ilgenA.Emit(OpCodes.Ret);

/////////////////////////////////////////////////////////////////////
// Create the types.
// 

classA.CreateType();
classB.CreateType();    

/////////////////////////////////////////////////////////////////////
// Save the assembly.
// 

assembly.Save(assemblyName.Name + ".dll");

Sorry this is a bit long.. :-P

这篇关于在.net中的代码中创建类类型#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆