简体   繁体   English

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

[英]Dynamically Create C# Properties From Database Columns

I don't know if this can be done in C#/.NET 2.0 but I want to be able to add a sql call to a method and build the properties based off the call. 我不知道这是否可以在C#/ .NET 2.0中完成,但我希望能够在方法中添加sql调用并根据调用构建属性。 So, it would be something like this: 所以,它会是这样的:

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

So, above the SomeTableId property would actually exist until the "SELECT" statement. 因此,在SomeTableId属性之上实际存在直到“SELECT”语句。 It checks for the columns and if exists creates the property 它检查列,如果存在则创建属性

It's possible through the Reflection.Emit namespace. 它可以通过Reflection.Emit命名空间。

This is a piece of code I wrote before, it converts as DataTable columns to a type, it may be helpful: 这是我之前编写的一段代码,它将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();
    }


}

Sure, it is possible to create a type at runtime, but it involves some fairly arcane black arts and I promise you it is more work than you want to do. 当然,可以在运行时创建一个类型,但它涉及一些相当神秘的黑色艺术,我保证你的工作比你想做的更多。

There is another solution to your requirements, i am sure. 我相信,您的要求还有另一种解决方案。

What are you planning to do with the object that is created/modified? 您打算如何处理创建/修改的对象?

perhaps another approach would be more appropriate. 也许另一种方法会更合适。

If I understand you correctly you are looking for a dynamic type, that is a type whose properties are not know until runtime. 如果我正确理解您正在寻找动态类型,那么这种类型的属性在运行时才会知道。 Those are to my knowledge only possible in dotNet 4 据我所知,只有在dotNet 4中才有可能

Is there any reason that the columns returned by the select are unknown at build time? 是否有任何原因导致select返回的列在构建时未知?

Not possible in .NET Framework 2.0. 在.NET Framework 2.0中不可能。
You could use a DataTable or KeyValuePairs to store the results. 您可以使用DataTable或KeyValuePairs来存储结果。

How would you know at compile time, something that is not settled before runtime? 在编译时你怎么知道在运行时之前没有解决的问题? This is dynamical binding, and you can't do it like that. 这是动态绑定,你不能这样做。

If anything you could modify you type at runtime with reflection.emit and use reflection to bind to the method at runtime. 如果您可以修改任何内容,则在运行时使用reflection.emit键入并使用reflection在运行时绑定到该方法。

But you are probably going about this the wrong way. 但你可能会以错误的方式解决这个问题。

I don't know if it's because you don't know the columns before you execute the query, in which case you should probably just store results in a keyvaluepair as suggested - otherwise you could just map to an existing type. 我不知道是不是因为你在执行查询之前不知道列,在这种情况下你可能只是按照建议将结果存储在keyvaluepair中 - 否则你只能映射到现有类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM