2012-02-24 49 views
1

因此,如果我尝试调用类型为IList的类的属性上的“清除”,则会引发它。如果我在IList类型的常量上做同样的事情,程序运行良好。在接口IList上的Expression.PropertyOrField上的Expression.Call <T>引发InvalidOperationException

class Program 
{ 
    static void Main(string[] args) 
    { 
     var parent = new Parent(new List<SomeClass>()); 
     parent.Data.Add(new SomeClass("Test")); 
     Console.WriteLine(parent.Data.Count); 

     var expr = Expression.Lambda(Expression.Call(Expression.Constant(parent.Data), "Clear", null, null), null); 
     var x = expr.Compile(); 
     x.DynamicInvoke(); 

     Console.WriteLine(parent.Data.Count); 

     var expr2 = Expression.Lambda(Expression.Call(Expression.PropertyOrField(Expression.Constant(parent), "Data"), "Clear", null, null), null); 
     var x2 = expr.Compile(); 
     x2.DynamicInvoke(); 

     Console.WriteLine(parent.Data.Count); 
     Console.ReadLine(); 

    } 

    public class Parent 
    { 
     public Parent(IList<SomeClass> data) 
     { 
      this.Data = data; 
     } 
     public IList<SomeClass> Data { get; set; } 
    } 
    public class SomeClass 
    { 
     public SomeClass(string value) { } 
    } 
} 

// output: 
// 1 
// 0 
// Exception of type: InvalidOperationException was thrown 

这只是一个bug还是有它这样做

回答

1

它那样做,因为“继承”的界面如何在.net中工作之前转换为ICollection的。试想一下,你有接口,这样的:

public interface ITest 
{ 
    string Property{get;set;} 
} 


public interface ISubTest : ITest 
{ 

} 

然后调用此:

typeof(ITest).GetProperty("Property"); // returns property 
typeof(ISubTest).GetProperty("Property"); // returns null 
你的情况铸造ICollection的将工作原因清除方法是在ICollection接口定义不IList接口上

左右。

更多关于接口类型推导的答案Why is the members of an inherited interface not available using reflection?

0

我会纪念谁与响应一些合乎逻辑的理由现有的连接错误或有此行为的答案,但一些合理的解释.. 。解决的办法是进行调用

 var expr2 = Expression.Lambda(Expression.Call(
      Expression.Convert(Expression.PropertyOrField(Expression.Constant(parent), "Data"), typeof(ICollection<>).MakeGenericType(parent.Data.GetType().GetGenericArguments())) 
      , "Clear", null, null), null); 
相关问题