2010-05-05 18 views
5

Tôi đã xem một bài đăng rất thú vị trên blog Fabio Maulo's. Đây là mã và lỗi nếu bạn không muốn chuyển đến url. Tôi đã xác định một lớp học chung mới như sau:
Đây có phải là một lỗ trong liên kết động trong C# 4?

public class TableStorageInitializer<TTableEntity> where TTableEntity : class, new() 
    { 
     public void Initialize() 
     { 
      InitializeInstance(new TTableEntity()); 
     } 

     public void InitializeInstance(dynamic entity) 
     { 
      entity.PartitionKey = Guid.NewGuid().ToString(); 
      entity.RowKey = Guid.NewGuid().ToString(); 
     } 

    } 

Lưu ý rằng InitializeInstance chấp nhận một tham số có loại động. Bây giờ để kiểm tra lớp này, tôi định nghĩa một lớp được lồng vào bên trong lớp Chương trình chính của tôi như vậy:

class Program 
     { 
      static void Main(string[] args) 
      { 
       TableStorageInitializer<MyClass> x = new TableStorageInitializer<MyClass>(); 
       x.Initialize(); 
      } 
      private class MyClass 
      { 
       public string PartitionKey { get; set; } 
       public string RowKey { get; set; } 
       public DateTime Timestamp { get; set; } 
      } 
     } 

Lưu ý: các lớp bên trong "MyClass" được khai báo là private.
Bây giờ nếu tôi chạy mã này, tôi nhận được một Microsoft.CSharp.RuntimeBinder.RuntimeBinderException trên dòng "entity.PartitionKey = Guide.NewGuid(). ToString()".
Phần thú vị, mặc dù là thông điệp của ngoại lệ cho biết "Đối tượng không chứa định nghĩa cho PartitionKey".
alt text http://img697.imageshack.us/img697/4188/testdl.png

Cũng lưu ý rằng nếu bạn thay đổi công cụ sửa đổi của lớp lồng nhau thành công khai, mã sẽ thực thi không có vấn đề gì. Vì vậy, những gì bạn nghĩ rằng thực sự đang xảy ra dưới mui xe? Vui lòng tham khảo bất kỳ tài liệu hướng dẫn nào nếu tài liệu này được ghi ở bất cứ đâu - bạn có thể tìm thấy?

Trả lời

5

Binder cố gắng làm việc ra một lớp học có thể truy cập để xử lý đối tượng như - trong trường hợp này, mã làm cho cuộc gọi đó không "biết" về lớp MyClass, vì vậy nó không "biết" về PartitionKey.

Tôi không biết làm thế nào triệt để điều này được ghi trong spec C# 4 - Tôi biết tôi đã có một cuộc trò chuyện email về nó với Chris Burrows mặc dù, vì vậy các chi tiết có thể là một nơi nào đó trên his blog :) Ghi nhớ rằng liên kết động đã thay đổi theo thời gian, vì vậy các bài đăng gần đây có thể chính xác hơn đối với mã RTM.

tôi nghĩ rằng nếu bạn đặt PartitionKey vào một giao diện nào mà các cụ lớp tư nhân, mà thể công việc - nhưng bạn phải thử nó.

Có nhiều "dấu hiệu" khác nhau xung quanh nhập động. giao diện thực hiện rõ ràng có một vấn đề tương tự:

public int Count(IList list) 
{ 
    int count1 = list.Count; // Fine 
    dynamic d = list; 
    int count2 = d.Count; // Should work, right? 
} 

này sẽ thất bại nếu bạn vượt qua trong một mảng - bởi vì mặc dù IList.Count tồn tại, nó được thực hiện một cách rõ ràng trong mảng - vì vậy đó là một chút như thế này:

string[] array = new string[10]; 
Console.WriteLine(array.Count); // Won't compile 

Các chất kết dính cố gắng xử lý đối tượng như loại bê tông của nó, không phải là IList, do đó sự thất bại ...

+0

Tôi đã từng nghĩ rằng việc sử dụng năng động là viết tắt của việc sử dụng sự phản chiếu cũ đơn giản. tốt nếu bạn thay thế thực hiện InitializeInstance để sử dụng sự phản chiếu. Bạn sẽ xây dựng trên đó, xin vui lòng? – Galilyou

+0

@Jon: Tôi e rằng tôi vẫn không hiểu các mảng bị mất đi như thế nào khi không triển khai tất cả các thuộc tính giao diện (mặc dù đưa nó vào một 'IList ' cho phép bạn gọi 'Đếm' !?) - bạn có thể làm phức tạp không ? * (ngoài ra, ý bạn là 'd.Count' ở trên?) * –

+0

Nevermind, [trả lời câu hỏi của riêng tôi] (http://msdn.microsoft.com/en-us/library/aa288461%28VS.71%29. aspx). –

Các vấn đề liên quan