假设我有以下课程:
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");
这不能编译,我不知道如何使用typeof
或GetType()
只返回decimal
,无论调用什么。
有没有办法做到这一点,或类似的东西?我认为这可以在编译时完成,因为类型已经知道,并且因为泛型是编译时构造。
谢谢!
答案 0 :(得分:5)
首先,请注意公共领域通常是一个非常糟糕的主意;但如果我们假设这是一个私人支持领域,那么这里有两个有趣的选择;
首先是利用泛型类推理;这不适用于返回类型,但适用于参数,因此您可以:
row.GetField("MyDecimalColumnName", out obj.someField);
其中:
GetField<T>(string name, out T value);
另一个技巧是使用隐式运算符,即让GetField(string)
将具有隐式转换运算符的虚拟对象返回到int
,decimal
等几种类型,并且操作员的工作/转换。有点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"});