从数据库列动态创建C#属性

时间:2010-02-14 14:42:43

标签: c# .net database properties

我不知道这是否可以在C#/ .NET 2.0中完成,但我希望能够向方法添加sql调用并根据调用构建属性。所以,它会是这样的:

QueryResult result = QueryDataTable.Query("SELECT ...", "DataConnection");
int someVar = result.SomeTableId;

因此,在“SELECT”语句之前,SomeTableId属性实际上会存在。它检查列,如果存在则创建属性

5 个答案:

答案 0 :(得分:3)

可以通过Reflection.Emit命名空间。

这是我之前编写的一段代码,它将DataTable列转换为类型,它可能会有所帮助:

using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

static class DataTableExtensions
{


    public static Type GetTableType(DataTable DTable)
    {

        // Create needed TypeBuilder helpers
        AppDomain myDomain = Thread.GetDomain();
        AssemblyName myAsmName = new AssemblyName("Anonymous");
        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);

        ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name);
        TypeBuilder myTypeBuilder = myModBuilder.DefineType(DTable.TableName, TypeAttributes.Public);

        foreach (DataColumn col in DTable.Columns) {

            var PropertyName = col.ColumnName;
            var PropertyType = col.DataType;

            FieldBuilder PropertyFieldBuilder = myTypeBuilder.DefineField("_" + PropertyName.ToLower, PropertyType, FieldAttributes.Private);

            PropertyBuilder PBuilder = myTypeBuilder.DefineProperty(PropertyName, PropertyAttributes.HasDefault, col.DataType, null);

            MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

            MethodBuilder getPropertyBuilder = myTypeBuilder.DefineMethod("get" + PropertyName, getSetAttr, col.DataType, Type.EmptyTypes);

            // Constructing IL Code for get and set Methods.
            ILGenerator GetPropGenerator = getPropertyBuilder.GetILGenerator();

            GetPropGenerator.Emit(OpCodes.Ldarg_0);
            GetPropGenerator.Emit(OpCodes.Ldfld, PropertyFieldBuilder);
            GetPropGenerator.Emit(OpCodes.Ret);

            MethodBuilder setPropertyBuulder = myTypeBuilder.DefineMethod("set_" + PropertyName, getSetAttr, null, new Type[] { col.DataType });

            ILGenerator SetPropGenerator = setPropertyBuulder.GetILGenerator();

            SetPropGenerator.Emit(OpCodes.Ldarg_0);
            SetPropGenerator.Emit(OpCodes.Ldarg_1);
            SetPropGenerator.Emit(OpCodes.Stfld, PropertyFieldBuilder);
            SetPropGenerator.Emit(OpCodes.Ret);

            PBuilder.SetGetMethod(getPropertyBuilder);

            PBuilder.SetSetMethod(setPropertyBuulder);
        }

        ConstructorInfo objCtor = typeof(object).GetConstructor(new Type[-1 + 1]);
        ConstructorBuilder pointCtor = myTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);

        ILGenerator ctorIL = pointCtor.GetILGenerator();

        // Constructing IL Code for the Type Constructor.
        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Call, objCtor);
        ctorIL.Emit(OpCodes.Ret);


        return myTypeBuilder.CreateType();
    }


}

答案 1 :(得分:1)

当然,可以在运行时创建一个类型,但它涉及一些相当神秘的黑色艺术,我向你保证这比你想做的更多。

我相信,您的要求还有另一种解决方案。

您打算如何处理创建/修改的对象?

或许另一种方法更合适。

答案 2 :(得分:0)

如果我正确理解您正在寻找动态类型,那么这种类型的属性在运行时才会知道。据我所知,只有在dotNet 4中才有可能

选择返回的列在构建时是否有未知原因?

答案 3 :(得分:0)

.NET Framework 2.0中不可能。
您可以使用DataTable或KeyValuePairs来存储结果。

答案 4 :(得分:0)

在编译时你怎么知道在运行时之前没有解决的问题?这是动态绑定,你不能那样做。

如果您可以修改任何内容,则在运行时使用reflection.emit键入并使用reflection在运行时绑定到该方法。

但你可能会以错误的方式解决这个问题。

我不知道是不是因为你在执行查询之前不知道列,在这种情况下你可能只是按照建议将结果存储在keyvaluepair中 - 否则你只能映射到现有类型。