2012-03-02 46 views
1

我一直在使用委托而不是反射来测试某些对象排序,并且它对字符串属性有效,但如果我尝试使用Int(或DateTime),它会失败并且抛出尝试访问Int或DateTime属性时,Open Delegate失败

错误绑定到目标方法。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var sample = new SampleClass() { Num = 13, Text = "Sample" }; 

     Console.WriteLine(ReadProp(sample,"Text")); //Works 
     Console.WriteLine(ReadProp(sample, "classProp")); //Works 
     Console.WriteLine(ReadProp(sample, "Num")); //Throws 'Error binding to target method.' 
    } 

    //Use a Delegate to improve speed of accessing property instead of reflection 
    static object ReadProp(SampleClass obj, string propName) 
    { 
     var method = obj.GetType().GetProperty(propName).GetGetMethod(); 
     var getForProp = (Func<SampleClass, object>)Delegate.CreateDelegate(typeof(Func<SampleClass, object>), null, method); 
     return getForProp(obj); 
    } 
} 

//A sample class for illustration purposes 
class SampleClass 
{ 
    public string Text { get; set; } 
    public int Num { get; set; } 
    public SampleClass classProp { get; set; } 
} 

我的问题是:为什么它的字符串或其他类而不是诠释或日期时间工作?

我可以看到,如果我改变Func<SampleClass, object>Func<SampleClass, int>它就会为我诠释工作,但我希望对象将两个工作。

回答

2

为什么它适用于字符串或其他类,但不适用于Int或DateTime?

因为它返回一个int的方法没有它返回一个object参考的方法。必须有一个拳击转换 - 所以一定要做到这一点,Delegate.CreateDelegate正试图提供一个代表只是调用委托并返回结果,没有值转换涉及。

这是轻微的疼痛做,但基本上我怀疑你应该要么来建设有一个适当的返回值的Func,并使用直接你应该通过包装委托其所谓的“真正”的代表去装箱结果。

(请注意,在你的示例代码,你每次都创建委托,这将是不超过反射快。希望你真正的代码是比较明智​​的:)

如果你看看你this code from protobuf-csharp-port会看到我有一个方法来做到这一点 - 一个lambda表达式调用强类型的委托,然后使用隐式转换为object(必要时进行装箱)以提供值。你应该能够使用非常相似的东西。但是,如果你正在排序,你真的 a Func<T, object>?如果您使用强类型的委托,您可能可以避免所有这些拳击。

+0

是的,我真正的代码只创建一次委托 – deepee1 2012-03-02 21:03:40

+0

感谢您的链接,我会看看。在我的情况下,我不知道设计时的返回类型,并且必须在运行时确定属性返回类型 – deepee1 2012-03-02 21:08:32

+0

@ deepee1:链接中的代码就是这样 - 你给它一个'MethodInfo',它给你一个'Func '。通用方法在创建委托时通过反射调用。 – 2012-03-02 21:13:03

相关问题