2012-02-24 55 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); 
相關問題