views:

286

answers:

5

Hello,

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

A: 

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?

Kjartan Þór Kjartansson
It can be a select statement for any of the tables in the database.
I see but how are you going to use these values?
Kjartan Þór Kjartansson
A: 

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

Zyphrax
That is entirely possible in .NET 2.0 using the System.Reflection.Emit
Rune FS
+1  A: 

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.

Sky Sanders
A: 

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.

Luhmann
+2  A: 

It's possible throught the Reflection.Emit .

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


}
Islam Ibrahim
Nice sample, but this feels a bit like using dynamite to start a bonfire. I agree with Aaronaught, keep simple things simple.
Zyphrax