Génération de code à la volée

De Banane Atomic
Aller à la navigationAller à la recherche
Csharp.svg
public class DynamicBuilder
{
    public static TypeBuilder CreateTypeBuilder(string assemblyName, string moduleName, string typeName)
    {
        // assemblyName here is not mandatory 
        var assemblyNameObject = new AssemblyName() { Name = assemblyName };

        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyNameObject, AssemblyBuilderAccess.Run);
        // sauvegarder l'assembly dans un fichier
        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyNameObject, AssemblyBuilderAccess.RunAndSave, filePath);

        ModuleBuilder module = assemblyBuilder.DefineDynamicModule(moduleName);

        // il n'est pas nécessaire de reconstruire à chaque fois un assemblage et un module pour définir un type
        // le module peut être réutilisé pour définir plusieurs types
        var type = module.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class, typeof(BaseClass));
        type.AddInterfaceImplementation(typeof(IInterface));
        return type;
    }

    public static void AddProperty(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);
    }
}
Csharp.svg
var typeBuilder = DynamicBuilder.CreateTypeBuilder("AAA", "MMM", "TTT");
DynamicBuilder.AddProperty(typeBuilder, "PPP", typeof(string));

Type generetedType = typeBuilder.CreateType();
dynamic generetedObject = Activator.CreateInstance(generetedType);

generetedObject.PPP = "VVV";