2010-07-31 12 views
2

Quand je regardais les capacités System.Linq.Expression (créer des arbres d'expression dans le code, les compiler, les exécuter) je me demandais si c'était possible pour la création de classe bien - spécifiquement les classes génériques.Créer un type de classe dans le code .net C#

Je m'attendrais à quelque chose comme Expression.Class() ou Expression.GenericClass(). En regardant les méthodes, je n'en ai vu aucune. Ce serait très pratique, car je pourrais créer des objets métier dynamiquement - à la volée. En fait, c'est ce dont j'ai besoin. S'il y a une autre approche à cela dans .net C# qui est aussi intéressante pour moi.

+0

Vous essayez de façon dynamique créer une classe ou essayer d'étendre des classes existantes avec des méthodes d'extension Linq? Créer des classes est en fait possible, mais je préférerais jeter un oeil à Reflection avec sa méthode Emit (http://msdn.microsoft.com/en-us/library/ms173183(VS.90).aspx) que Linq, qui est la plupart du temps une technologie axée sur les requêtes, pas un générateur de métadonnées. Vous devrez utiliser MSIL cependant. – Marcanpilami

+0

J'essaie de créer dynamiquement une classe. Une classe Model dans MVC - par exemple. Plus tard - après l'avoir créé - je dois l'interroger avec Linq. Dans le cadre de la classe MVC Controller par exemple. –

Répondre

4

Il est un exemple de la façon de le faire dans All-In-One cadre projet 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"); 

Désolé, c'est un peu long .. :-P

+0

Grand- merci. Je vais essayer ça. –

0

Vous devriez regarder dans le CSharpCodeProvider ou vous pouvez regarder dans la fonctionnalité dynamic de .Net4. Les deux vous permettront de créer de nouveaux types d'objets dans le code qui peuvent être instanciés.

Questions connexes