user204588
user204588

Reputation: 1633

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. 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. It checks for the columns and if exists creates the property

Upvotes: 1

Views: 3399

Answers (5)

Islam Yahiatene
Islam Yahiatene

Reputation: 1469

It's possible through the Reflection.Emit namespace.

This is a piece of code I wrote before, it converts as DataTable columns to a type, it may be helpful:

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();
    }


}

Upvotes: 3

Luhmann
Luhmann

Reputation: 3890

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.

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.

Upvotes: 0

Sky Sanders
Sky Sanders

Reputation: 37074

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.

Upvotes: 1

Yvo
Yvo

Reputation: 19263

Not possible in .NET Framework 2.0.
You could use a DataTable or KeyValuePairs to store the results.

Upvotes: 0

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

Is there any reason that the columns returned by the select are unknown at build time?

Upvotes: 0

Related Questions