Динамически создавать свойства C # из столбцов базы данных - PullRequest
1 голос
/ 14 февраля 2010

Я не знаю, можно ли это сделать в C # /. NET 2.0, но я хочу иметь возможность добавить вызов sql в метод и построить свойства на основе этого вызова. Итак, было бы что-то вроде этого:

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

Таким образом, выше свойство SomeTableId будет фактически существовать до оператора "SELECT". Проверяет столбцы и, если существует, создает свойство

Ответы [ 5 ]

3 голосов
/ 14 февраля 2010

Это возможно через пространство имен 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 голос
/ 14 февраля 2010

Конечно, можно создать тип во время выполнения, но он включает в себя несколько довольно тайных черных искусств, и я обещаю вам, что это больше работы, чем вы хотите.

Существует другое решение ваших требований, я уверен.

Что вы планируете делать с созданным / измененным объектом?

возможно, другой подход был бы более уместным.

0 голосов
/ 14 февраля 2010

Как бы вы узнали во время компиляции то, что не было решено до выполнения? Это динамическое связывание, и вы не можете так делать.

Если вы можете что-то изменить, наберите во время выполнения с помощью refle.emit и используйте отражение для привязки к методу во время выполнения.

Но вы, вероятно, ошибаетесь.

Я не знаю, связано ли это с тем, что вы не знаете столбцы до выполнения запроса, и в этом случае вам, вероятно, следует просто сохранить результаты в ключевой паре значений, как это было предложено - в противном случае вы можете просто сопоставить существующий тип.

0 голосов
/ 14 февраля 2010

Невозможно в .NET Framework 2.0.
Вы можете использовать DataTable или KeyValuePairs для хранения результатов.

0 голосов
/ 14 февраля 2010

Если я правильно вас понимаю, вы ищете динамический тип, то есть тип, свойства которого неизвестны до времени выполнения. Насколько мне известно, это возможно только в dotNet 4

Есть ли причина, по которой столбцы, возвращаемые выбором, неизвестны во время сборки?

...