Создать тип класса в коде в .net c # - PullRequest
2 голосов
/ 31 июля 2010

Когда я искал возможности System.Linq.Expression (создание деревьев выражений в коде, компиляция их, их выполнение), я спрашивал себя, возможно ли это и для создания классов - в частности, для общих классов.

Я бы ожидал что-то вроде Expression.Class () или Expression.GenericClass (). Глядя на методы, я не видел ни одного из них. Это было бы очень практично, поскольку я мог строить бизнес-объекты динамически - на лету. На самом деле это то, что мне нужно. Если есть другой подход к этому в .net c #, это также представляет интерес для меня.

Ответы [ 2 ]

4 голосов
/ 31 июля 2010

Есть пример того, как это сделать в проекте All-In-One Framework codeplex. 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");

Извините, это немного долго ..: -P

0 голосов
/ 31 июля 2010

Вы должны заглянуть в CSharpCodeProvider или посмотреть в динамическую функцию .Net4. Оба позволят вам создавать новые типы объектов в коде, которые могут быть созданы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...