2016-02-29 23 views
144

Chúng tôi có một chương trình rất đơn giản gọi phương thức tĩnh Type.GetType. Cả hai ví dụ sẽ trả về một thể hiện kiểu hợp lệ. Chỉ có cái thứ hai thực sự là. Có vẻ như có điều gì đó kỳ lạ đang xảy ra với thu thập dữ liệu ngăn xếp được sử dụng bởi GetType, nhưng vấn đề chính xác ở đây là gì? Có lỗi hay một số tính năng tối nghĩa không?Tại sao GetType() không thể tìm thấy kiểu khi được gọi thông qua một ủy nhiệm nhóm phương thức?

public class TestClass { } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fullName = typeof(TestClass).FullName; 
     Console.WriteLine("Full name: {0}", fullName); 

     new[] { fullName }.Select(Type.GetType).ToList().ForEach(t => Console.WriteLine("Method group: '{0}'", t)); 
     new[] { fullName }.Select(t => Type.GetType(t)).ToList().ForEach(t => Console.WriteLine("Closure: '{0}'", t)); 
    } 
} 

Chạy:

Full name: GetTypeBeingWeird.TestClass 
Method group: '' 
Closure: 'GetTypeBeingWeird.TestClass' 
+0

Tôi có nên đóng cái cũ hơn không? Không chắc chắn, chào đón ý kiến ​​về điều này ... – nawfal

Trả lời

165

Điều này thực sự thú vị. Đó là một hỗn hợp của các hành vi của Type.GetType(string) về lắp ráp gọi điện thoại, và làm thế nào nhóm phương pháp chuyển đổi hoạt động.

Thứ nhất, tài liệu Type.GetType bao gồm này:

Nếu typeName bao gồm các không gian tên nhưng không phải là tên lắp ráp, phương pháp này chỉ tìm kiếm lắp ráp các đối tượng gọi điện thoại và Mscorlib.dll, theo thứ tự đó.

Trong cuộc gọi đầu tiên của bạn, bạn sẽ chuyển một đại biểu gọi Type.GetType ... nhưng không được gọi riêng từ hội đồng của bạn. Nó được gọi là trực tiếp trực tiếp từ phương pháp Select trong LINQ ... nếu bạn nhìn vào dấu vết ngăn xếp từ bên trong Type.GetType, bạn sẽ thấy Select là người gọi trực tiếp, tôi tin.

Trong cuộc gọi thứ hai của bạn, bạn đang đi qua một đóng cửa gọi Type.GetType và cuộc gọi đó nằm trong hội đồng của bạn.

Đó là lý do tại sao nó tìm loại trong trường hợp thứ hai nhưng không phải là loại đầu tiên. Đây là tiếp tục xác nhận bằng cách xác định một loại mà là ở việc lắp ráp LINQ:

var fullName = typeof(Enumerable).FullName; 

Sau đó, kết quả là cách đối diện tròn:

Full name: System.Linq.Enumerable 
Method group: 'System.Linq.Enumerable' 
Closure: '' 

Nếu bạn chỉ định một cái gì đó trong mscorlib (ví dụ typeof(string).FullName) sau đó cả hai phương pháp tiếp cận hoạt động:

Full name: System.String 
Method group: 'System.String' 
Closure: 'System.String' 

Cách để giải quyết vấn đề này khi tìm kiếm lớp học của bạn, vẫn sử dụng nhóm phương pháp, chỉ đơn giản là cung cấp lắp ráp tên ified thay thế:

var fullName = typeof(TestClass).AssemblyQualifiedName; 
+16

Wow, bằng cách sử dụng hội đồng kêu gọi như là một đầu vào ẩn là ghê tởm. Lỗi thú vị, mặc dù. – usr

+5

Sử dụng tính năng gọi điện thoại thay vì nhập hoặc thực thi theo mặc định có thể là (và tôi chắc chắn thực sự là một quyết định có chủ ý). Một lý do tôi có thể nghĩ đến là tránh giả mạo kiểu trong các cuộc gọi mscorelib tới Type.GetType() nếu assembly/thực thi đã khai báo cùng một không gian tên và loại tên khớp với mscorelib. "Hideo" của một người đàn ông là một người đàn ông khác không có ass của mình đã trao lại cho anh ta thông qua việc cướp thư viện std. – Serjx86

+5

API không nên dùng * bất kỳ * assembly nào làm đầu vào bị ẩn. Nó sẽ được chỉ định bởi người gọi. Sử dụng cụm từ nhập cảnh sẽ gần như là xấu. Tên loại không có tên lắp ráp chỉ đơn giản là mơ hồ. Không có chiến lược định hướng tốt nào có thể. – usr

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