2011-04-01 54 views
4
class Mock 
{ 
    public static explicit operator String(Mock s) 
    { 
     return "ok"; 
    } 
} 

static T GetValue<T>(object o) 
{ 
    return (T)o; 
} 

Mock m = new Mock(); 
var v1 = (string) m; 
var v2 = GetValue<string>(m); // InvalidCastException is thrown. 
           // How to modify GetValue method 
           // internally, without changing its 
           // signature, for this casting to work ? 

問候如何從對象引用

回答

2

兩個選項進行轉換:

  • 使用反射來找到轉換和調用它
  • 使用動態類型,如果你正在使用C#4

使用反射很可能是痛苦的。動態方法比較簡單,如果你能擺脫它:

public static T GetValue<T>(dynamic d) 
{ 
    return (T) d; 
} 

這並不是簽名特別劇烈的變化,但如果你想保持完全相同一樣,你可以使用:

public static T GetValue<T>(object o) 
{ 
    dynamic d = o; 
    return (T) d; 
} 
1

直接鑄造的成功並且GetValue方法失敗的原因是因爲直接流延法是使用explicitcast操作者在Mock<T>類型。此顯式轉換運算符在通用版本中不可用,因爲C#編譯器只能看到T,因此不會綁定到隱式轉換運算符,而是選擇執行CLR轉換。

得到這個工作,最簡單的方法是增加一個接口來表示這種轉換,然後約束T實現接口

interface IConvertToString { 
    string Convert(); 
} 

public class Mock : IConvertToString { 
    public string Convert() { 
    return "ok"; 
    } 
} 

public static T GetValue<T>(T o) where T : IConvertToString { 
    return o.ConvertToString(); 
} 
0
如何

一下:var v2 = GetValue<string>((string)m);

這不會修改GetValue方法,而是將發送給它的參數強制轉換。你保留你的簽名。演員看起來有點多餘,但你必須指定GetValue的類型......