2011-04-01 55 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的类型......