【问题标题】:Specify generics type using a field使用字段指定泛型类型
【发布时间】:2012-03-29 23:15:16
【问题描述】:

假设我有以下课程:

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,不管它会被调用。

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

谢谢!

【问题讨论】:

  • 看看here
  • 编译器不能推断那个类型参数吗?
  • @davisoa 不用于 return 值,否
  • 哦,那是限制,我不确定。
  • 为什么不只是row.Field&lt;myClass.myDecimal&gt;("MyDecimalColumnName")

标签: c# generics datarow typeof gettype


【解决方案1】:

首先,请注意公共字段通常是一个非常糟糕的主意;但如果我们假设这是一个私有的支持字段,这里有 2 个有趣的选项;

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

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 这里的最佳选项是使用诸如 ORM 或 micro-ORM 之类的工具来为您加载值,并且根本不要使用 DataRow

另一个简单的选择就是走老派:

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

我的意思是 - .Field&lt;T&gt; 真的对你有那么大的帮助吗?你真的经常重构你的类以至于这值得担心吗?

【讨论】:

  • 我喜欢您的row.GetField 建议,但我想知道为什么我不能明确设置返回值的类型。至于使用Field&lt;T&gt;,我之所以使用它是因为它有助于使用可空类型(DataRow 为可空列返回DBNull.Value,为不存在的列返回null)。例如,如果 MyColumn 为 null,decimal? x = (decimal?)row["MyColumn"] 将失败,但如果 MyColumn 不存在,则不会失败。
  • @Matthew 是的,不要让我开始疯狂;我不是DBNull.Value的粉丝
  • @Matthew 当然,当您通过摆脱那些公共字段来修复代码时,它不会那么方便地工作。暗示。提示提示。提示。
  • 是的,我知道使用公共字段通常是不好的形式,但这些对象只是 POCO。
【解决方案2】:

您可以使用反射来动态构造适当的泛型方法:

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

【讨论】:

  • 我可能会将 could 用斜体表示。是的,它有效,但绝对不是最佳解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
相关资源
最近更新 更多