使用字段指定泛型类型

时间:2012-03-13 14:25:06

标签: c# generics datarow typeof gettype

假设我有以下课程:

public class MyClass
{
    public decimal myDecimal;
    public string myString;
}

我想使用DataRowExtensions方法Field<>

目前,我正在使用这样的类:

MyClass myClass = new MyClass();
myClass.myDecimal = row.Field<decimal>("MyDecimalColumnName");
myClass.myString = row.Field<string>("MyStringColumnName");

但是,如果我决定将myDecimal的类型更改为decimal以外的其他类型,我希望调用row.Field来反映正确的数据。

我想要类似于以下语法的内容:

myClass.myDecimal = row.Field<typeof(myClass.myDecimal)>("MyDecimalColumnName");

这不能编译,我不知道如何使用typeofGetType()只返回decimal,无论调用什么。

有没有办法做到这一点,或类似的东西?我认为这可以在编译时完成,因为类型已经知道,并且因为泛型是编译时构造。

谢谢!

2 个答案:

答案 0 :(得分:5)

首先,请注意公共领域通常是一个非常糟糕的主意;但如果我们假设这是一个私人支持领域,那么这里有两个有趣的选择;

首先是利用泛型类推理;这不适用于返回类型,但适用于参数,因此您可以:

row.GetField("MyDecimalColumnName", out obj.someField);

其中:

GetField<T>(string name, out T value);

另一个技巧是使用隐式运算符,即让GetField(string)将具有隐式转换运算符的虚拟对象返回到intdecimal等几种类型,并且操作员的工作/转换。有点hacky,但会工作 - 语法将是:

myClass.myDecimal = row.Field("SomeColumn")

使用:

SomeDummyType GetField(string name);

并且SomeDummyType具有隐式静态转换运算符或多个。

然而! IMO best 选项是使用ORM或micro-ORM等工具为您加载值,并且根本不使用DataRow

另一个简单的选择就是去上学:

myClass.myDecimal = (decimal)row["SomeColumn"];

我的意思是 - .Field<T>真的帮助了你这么多吗?你是否真的经常重构你的课程,这值得担心呢?

答案 1 :(得分:1)

您可以使用反射来动态构建正确的泛型方法:

MyClass myClass = new MyClass();
var myType = typeof(MyClass.myDecimal);
var myMethod = Type.GetType("System.Data.DataRowExtensions")
   .GetMethod("Field", new[]{typeof(DataRow), typeof(string));
var genericMethod = myMethod.MakeGenericMethod(new[]{myType});

myClass.myDecimal = genericMethod.Invoke(row, new object[]{"MyDecimalColumnName"});
相关问题