C#练习题答案: 在运行时创建一个简单的类【难度:5级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战

在运行时创建一个简单的类【难度:5级】:

答案1:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

public static class Kata
{
   
    public static bool DefineClass(string className, Dictionary<string, Type> properties, ref Type actualType)
    {
   
        actualType = MyTypeBuilder.CompileResultType(className, properties);
        return actualType != null;
    }
}

public static class MyTypeBuilder
{
   
    private const string _AssemblyName = "RuntimeAssembly";
    private const string _ModuleName = "MainModule";

    private static Lazy<ModuleBuilder> moduleBuilder = new Lazy<ModuleBuilder>(() =>
    {
   
        var an = new AssemblyName(_AssemblyName);
        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
        return assemblyBuilder.DefineDynamicModule(_ModuleName);
    });


    public static Type CompileResultType(string className, Dictionary<string, Type> props)
    {
   
        Assembly dynamicAssembly = AppDomain.CurrentDomain.GetAssemblies()
            .FirstOrDefault(a => a.FullName.StartsWith(_AssemblyName + ","));
        Type existingType = (dynamicAssembly == null) ? null : dynamicAssembly.GetType(className);
        if (existingType != null) return null;

        TypeBuilder tb = GetTypeBuilder(className);
        ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

        foreach (var field in props)
            CreateProperty(tb, field.Key, field.Value);

        Type objectType = tb.CreateType();
        return objectType;
    }

    private static TypeBuilder GetTypeBuilder(string className)
    {
   
        TypeBuilder tb = moduleBuilder.Value.DefineType(className,
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                null);
        return tb;
    }

    private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
    {
   
        FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

        PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
        MethodBuilder getPropMthdBldr = tb.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 =
            tb.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);
    }
}

答案2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

public static class Kata
{
   

    private static AssemblyBuilder AssemblyBuilder {
    get; set; }
    private static ModuleBuilder ModuleBuilder {
    get; set; }
    private static AssemblyName AName {
    get; set; }

    private static void CreateProp(String pName, Type type, TypeBuilder typeBuilder)
    {
   

        FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + pName, type, FieldAttributes.Private);

        PropertyBuilder pBuilder = typeBuilder.DefineProperty(pName, PropertyAttributes.HasDefault, type, null);

        MethodBuilder getMethBuilder = typeBuilder.DefineMethod("get_" + pName,
            MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
            type, null);
            
        ILGenerator iLGen = getMethBuilder.GetILGenerator();

        iLGen.Emit(OpCodes.Ldarg_0);
        iLGen.Emit(OpCodes.Ldfld, fieldBuilder);
        iLGen.Emit(OpCodes.Ret);

        MethodBuilder setMethBuilder = typeBuilder.DefineMethod("set_" + pName,
            MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
            null, new Type[1] {
    type });

        iLGen = setMethBuilder.GetILGenerator();

        iLGen.Emit(OpCodes.Ldarg_0);
        iLGen.Emit(OpCodes.Ldarg_1);
        iLGen.Emit(OpCodes.Stfld, fieldBuilder);
        iLGen.Emit(OpCodes.Ret);


        pBuilder.SetGetMethod(getMethBuilder);
        pBuilder.SetSetMethod(setMethBuilder);

    }

    public static bool DefineClass(String className, Dictionary<String, Type> properties, ref Type actualType)
    {
   
        if (AName == null &amp;&amp; AssemblyBuilder == null &amp;&amp; ModuleBuilder == null)
        {
   
            AName = new AssemblyName("RuntimeAssembly");
            AName.Version = new Version(1, 0, 0, 0);
            AName.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;
            AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(AName, AssemblyBuilderAccess.Run);
            ModuleBuilder = Assembly
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值