2009-07-10 32 views
9

Ok, vì vậy chúng ta đều biết Reflecttion có ít thời gian biểu diễn hơn "newing" một cá thể lớp, và trong nhiều trường hợp, điều này là tốt tùy thuộc vào các yêu cầu ứng dụng.Cách tạo các lớp .NET hiệu năng cao bằng cách sử dụng sự phản chiếu?

CÂU HỎI: Làm cách nào chúng ta có thể tạo các lớp .NET hiệu suất cao bằng cách sử dụng chiến lược ràng buộc muộn (Phản chiếu).

Tôi có yêu cầu hiện tại yêu cầu các cá thể lớp được tạo bằng cách sử dụng sự phản chiếu (CreateInstance), nhưng hiệu suất là rất quan trọng. Trong tình huống của tôi, tôi đang tạo ra các trường hợp cho mỗi tin nhắn SMS đến trong ứng dụng của chúng tôi. Trong quá trình sản xuất, điều này có thể dễ dàng hơn một triệu mỗi ngày.

Tôi muốn nghe và chia sẻ một số ý tưởng về cách tạo các lớp .NET mà không trực tiếp tham khảo các lớp trong mã, ví dụ bằng cách sử dụng Reflection. Tôi cũng nghĩ nếu có cách nào đó để lưu trữ một Nhà máy có thể cải thiện thời gian "Sáng tạo"

+0

chờ đợi C# 4.0 i giả :) –

+4

Làm thế nào sẽ C# 4.0 giúp đỡ, chính xác? –

+0

Sử dụng Reflection để tạo một thể hiện của một đối tượng là tầm thường trong 99,9% các trường hợp. Phản ánh trong .NET cực kỳ nhanh chóng - chỉ cần viết nó và quay lại sau nếu đó là một vấn đề. Đảm bảo nó sẽ không được. –

Trả lời

6

Tôi không nghĩ một triệu mỗi ngày là quá nhiều cho một cuộc gọi phản chiếu đơn giản. Tôi tin rằng bạn đang quá tối ưu hóa nhưng dù sao, như bạn đã nói, chỉ cần tạo một lớp nhà máy bằng cách sử dụng một cuộc gọi Activator.CreateInstance và bộ nhớ cache duy nhất mà một. Các phiên bản thực tế sẽ được tạo bằng cách sử dụng cuộc gọi phương thức CreateInstance() trên đối tượng được trả về.

public interface IClassFactory { 
    IClass CreateInstance(); 
} 

public interface IClass { 
    // your actual class interface. 
} 

public class DefaultClassFactory : IClassFactory { 
    public IClass CreateInstance() { 
     return new DefaultClass(); // the implementation class 
    } 
} 

Một nơi nào đó bạn sẽ có một lĩnh vực static loại IClassFactory mà bạn sẽ thiết lập một lần với một thể hiện của các DefaultClassFactory hay bất kỳ lớp học khác được quy định trong tập tin cấu hình hoặc bất cứ điều gì.

+0

Sự nấc cục duy nhất có thể xảy ra ở đây là nếu ứng dụng đa luồng, bạn có thể có nhiều cuộc gọi khác nhau bằng cách sử dụng cùng một trường hợp, và kết thúc với các trường hợp với trạng thái hỗn hợp. Có lẽ trả lại một bản sao của đối tượng nếu đó là một vấn đề? – Matt

+0

Huh? Tại sao? Nhà máy sẽ luôn tạo ra một thể hiện mới và nó an toàn cho chính nó vì nó không có trạng thái bên trong. –

+1

@ Ông nói rằng một nhà máy tĩnh, không phải là lớp chính nó là tĩnh. Nhà máy rất dễ dàng để làm cho thread-an toàn. –

11

1 triệu mỗi ngày không nhiều; Tôi chỉ cần sử dụng Activator.CreateInstance (một thử nghiệm nhanh chóng sử dụng Activator.CreatInstance(Type) cho thấy rằng trên máy tính xách tay thấp của tôi nó có thể tạo ra 1M đối tượng từ một Type trong ~ 2s).

suy nghĩ về tạo các đối tượng một cách nhanh chóng:

  • Generics sử dụng và : new() chế (zero nỗ lực)
  • sử dụng DynamicMethod và viết IL (không khó)

An thực hiện các new cách tiếp cận (mà không cần ràng buộc : new() bên ngoài) được hiển thị ở đây: ObjectFactory.cs.

Đối với một ví dụ IL, xem dapper-dot-netil.Emit(OpCodes.Newobj, ...)

+1

+1 lớp tiện dụng. – RichardOD

+1

mới thông qua ràng buộc chung không phải là đặc biệt nhanh chóng ... – flq

+0

@Frank: chỉ khi nhà xây dựng của bạn không phải là đặc biệt nhanh chóng chính nó, trong trường hợp không có gì sẽ giúp bạn tiết kiệm. 'new()' thông qua kết quả ràng buộc chung trong một lời gọi hàm tạo trực tiếp thực tế, vì vậy nó không nhanh hơn. – jerryjvl

5

Vài suy nghĩ:

  • Giữ một ví dụ của từng loại xung quanh, một khi bạn tìm thấy bạn cần nó. Sau đó, thay vì CreateInstance, Clone nó.
  • Khi bạn đã tạo phiên bản đầu tiên, hãy giữ Kiểu của cá thể chung quanh. sau đó sử dụng Activator.CreateInstance (Loại)

Cache thể hiện để sao chép hoặc nhập vào Dictionary<string,Type> hoặc Dictionary<string,object>.

+0

Nhân bản nhanh hơn việc tạo một cá thể từ một đại biểu được lưu trong bộ nhớ cache? Tôi không nghĩ rằng nó là tốt nhất, nên tốt nhất là để cache các nhà thầu lớp? đây có phải là đại biểu không? nếu sự phản chiếu được sử dụng để có được loại và sau đó để tạo ra một thể hiện, bạn sẽ nhận được các nhà thầu từ các loại hoặc trường hợp. Có thể thêm một số mã mẫu. Sự hiểu biết của tôi là bộ nhớ đệm của ctor của các loại trong từ điển sẽ là nhanh nhất. – Seabizkit

0

Xác định và triển khai giao diện thay vì sử dụng phản chiếu.

1

TUYỆT VỜI! Phương pháp tiếp cận nhà máy Class dường như là cách để đi đến đây.

Sử dụng kết hợp Assembly.CreateInstance(typeNameString) theo yêu cầu đầu tiên, sau đó nhớ cache Type trong nhà máy.

Khi có cuộc gọi tiếp theo, hãy sử dụng Activator.CreateInstance(type).

Sử dụng phương pháp này chậm hơn 20% so với sử dụng toán tử Mới gốc. Không có vấn đề lớn ở đó!

Thống kê cho việc tạo ra 10 triệu Employee đối tượng như sau:

  • 8 giây sử dụng toán tử new

  • 10 giây bằng cách sử dụng Nhà máy/Loại/phương pháp Cache.

Đây là đoạn mã mẫu nếu có ai quan tâm:

private IEmployee CachedClassFactory() 
{ 
    if(_typeCache == null) 
    { 
     // This is a one time hit to load the type into the cache 
     string typeName = "ClassFactoryTest.Employee"; 
     string assemblyName = "ClassFactoryTest"; 
     Assembly assembly = Assembly.Load(assemblyName); 
     IEmployee employee = assembly.CreateInstance(typeName) as IEmployee;       
     _typeCache = employee.GetType(); 
    } 

    IEmployee instance = Activator.CreateInstance(_typeCache) as IEmployee; 

    instance.FirstName = "Raiford"; 
    instance.LastName = "Brookshire"; 
    instance.Birthdate = DateTime.Now.AddYears(-35); 
    instance.Age = 35; 

    return instance;  
} 
+0

Tôi nghĩ bạn có thể cải thiện khi sử dụng cây biểu thức. Xem phần này để biết [ví dụ] (http://stackoverflow.com/questions/367577/why-does-the-c-sharp-compiler-emit-activator-createinstance-when-calling-new-in). – nawfal

+0

không chắc chắn những gì bạn đang hiển thị ở đây về từ ngữ, làm thế nào một giá trị được lưu trữ sẽ chậm hơn 20%? – Seabizkit

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