2012-03-13 38 views
1

假設我有以下類:指定泛型類型中使用領域

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,無論將被調用。

有沒有辦法做到這一點,或類似的東西?我認爲這可以在編譯時完成,因爲類型是已知的,因爲泛型是編譯時構造。

謝謝!

+0

看看[這裏](http://stackoverflow.com/q/196936/754438) – Reniuz 2012-03-13 14:32:04

+0

不能編譯*推斷*該類型的參數? – davisoa 2012-03-13 14:32:19

+2

@davisoa不用於* return *值,不是 – 2012-03-13 14:32:42

回答

5

首先,請注意,公共領域通常是一個非常糟糕的主意;但如果我們假設這是一個私人支持領域,這裏有兩個有趣的選擇;

首先是利用泛型類型推斷;這並不爲返回類型的工作,但確實的參數,所以你可以有:

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

這裏說的:

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

另一個技巧是使用隱含的運營商,即有GetField(string)返回一個虛擬對象,它具有隱式轉換運算符到幾種類型,如int,decimal等,並在運算符中進行工作/轉換。有點哈克,但會工作 - 語法爲:

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

有:

SomeDummyType GetField(string name); 

,並有一個隱含的靜態轉換運算符或幾個SomeDummyType

但是! IMO best這裏的選項是使用諸如ORM或micro-ORM之類的工具爲您加載值,並且完全不使用DataRow

另一種簡單的選擇就是去舊學校:

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

我的意思是 - 是.Field<T>真正幫助你所有的東西?你是否真的經常重構你的課程,這是值得擔心的嗎?

+0

我喜歡你的'row.GetField'建議,但我想知道爲什麼我不能明確地設置返回值的類型。至於使用'Field ',我使用它,因爲它有助於使用可空類型(DataRow爲可空列返回'DBNull.Value',爲不可列的列返回'null')。例如'小數?如果MyColumn爲空,x =(decimal?)row [「MyColumn」]'將失敗,但如果MyColumn不存在則不會失敗。 – Matthew 2012-03-13 14:43:55

+1

@Matthew是的,不要讓我開始瘋狂;我不是'DBNull.Value'的粉絲 – 2012-03-13 14:46:22

+0

我想我會和你的'row.GetField'例子一起去,謝謝! – Matthew 2012-03-13 14:47:26

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

我可能會在此上面顯示_could_。是的,但它絕對不是最佳解決方案。 – 2012-03-13 14:37:20