我不知道这是否可以在C#/ .NET 2.0中完成,但我希望能够向方法添加sql调用并根据调用构建属性。所以,它会是这样的:
QueryResult result = QueryDataTable.Query("SELECT ...", "DataConnection");
int someVar = result.SomeTableId;
因此,在“SELECT”语句之前,SomeTableId属性实际上会存在。它检查列,如果存在则创建属性
答案 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中 - 否则你只能映射到现有类型。