2010-06-07 11 views
25

Mã bên dưới hoạt động rất tốt. Nếu các phương thức GetUse nằm trong các hội đồng khác nhau, mã không thành công với RuntimeBinderException. Điều này là do hệ thống runtime .Net chỉ đảm bảo tính phổ biến của các loại vô danh (<string, int> trong trường hợp này) trong các assembly.Trả lại/tiêu thụ loại ẩn danh động trên các ranh giới lắp ráp

Có cách nào để đánh lừa hệ thống thời gian chạy để khắc phục điều này không? Tôi có thể kiểm tra đối tượng trong trình gỡ lỗi ở bên Use và trình gỡ lỗi có thể xem các thuộc tính có liên quan.

class Program 
{ 
    static void Main(string[] args) 
    { 
     UsePerson(); 
     Console.ReadLine(); 
    } 

    public static void UsePerson() 
    { 
     var person = GetPerson(); 

     Console.WriteLine(person.Name); 
    } 

    public static dynamic GetPerson() 
    { 
     return new { Name = "Foo", Age = 30 }; 
    } 
} 

Trả lời

31

Sử dụng số ExpandoObject thay vì loại ẩn danh. Điều này sẽ cho phép bạn vượt qua các ranh giới lắp ráp một cách an toàn:

public static dynamic GetPerson() 
{ 
    dynamic person = new ExpandoObject(); 
    person.Name = "Foo"; 
    person.Age = 30; 

    return person; 
} 

Nói chung, các loại ẩn danh chỉ nên được sử dụng trong cùng một phương pháp mà chúng được tạo ra. Việc trả về một kiểu vô danh từ một phương thức, nói chung, sẽ gây ra nhiều vấn đề hơn là giải quyết nó.

8

Nguyên nhân của sự cố là các loại ẩn danh nằm bên trong các hội đồng. Đó là lý do tại sao Dynamic Language Runtime không cho phép bạn truy cập các thuộc tính từ một assembly khác.

Một giải pháp được giải thích trong số post này. Bạn có thể đặt một thuộc tính tùy chỉnh trong assembly để định nghĩa kiểu ẩn danh cho phép assembly khác truy cập vào nội bộ của nó.

Một giải pháp khác là trả về đối tượng của lớp công khai (có thuộc tính công khai). Điều đó sẽ, tất nhiên, tiêu diệt những lợi thế của loại vô danh.

Giải pháp thứ ba sẽ sử dụng số ExpandoObject như được đề xuất bởi Reed Copsey.

Nếu bạn vẫn muốn sử dụng loại ẩn danh, bạn có thể viết một lớp động "trang trí" mọi loại ẩn danh và hiển thị các thành viên của nó. Một lớp như vậy sẽ phải thực hiện giao diện IDynamicMetaObjectProvider và truy cập đối tượng được trang trí thông qua sự phản chiếu. Có thể, công cụ này đã được thực hiện bởi một ai đó ngoài kia.

+0

Liên kết trỏ đến bài đăng bị hỏng –

+1

Giải pháp "1" trong bài đăng trên thực sự khá thú vị. Về cơ bản [assembly: InternalsVisibleTo ("SomeOtherAssembly")] trong assemblyinfo.cs của bạn hoạt động khá tốt. – OFConsulting

0

ngẫu hứng giao diện

http://code.google.com/p/impromptu-interface/

sẽ cho phép bạn sử dụng các ví dụ loại vô danh qua các biên giới nhưng bạn phải khai báo một giao diện khớp với chữ ký của nó hoặc ít nhất là những gì bạn muốn truy cập từ chữ ký của nó.

1

Đây là giải pháp của người nghèo; Newtonsoft.Json để giải cứu, như roundtrip serialization tạo ra các thể hiện kiểu động có thể nhìn thấy để lắp ráp/làm việc của bạn.

public static class TypeExt 
{ 
    // roundtrip json serialization to enable access to dynamic members and properties originating from another assembly 
    public static T JClone<T>(this T source) { return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source)); } 
}