2009-12-16 6 views
21

Trình khởi tạo mô-đun là một tính năng của CLR không có sẵn trực tiếp trong C# hoặc VB.NET. Chúng là các phương thức tĩnh toàn cầu có tên là .cctor được bảo đảm để chạy trước bất kỳ mã nào khác (kiểu khởi tạo, các hàm tạo tĩnh) trong một assembly được thực hiện. Gần đây tôi muốn sử dụng này trong một dự án và sử dụng hacked together my own solution (console program/msbuild task) Mono.Cecil, nhưng tôi đã tự hỏi:Trình khởi tạo mô-đun trong C#

  1. Có cách nào để lừa trình biên dịch C# vào phát intializers module? Bất kỳ thuộc tính nào (ví dụ: CompilerGenerated, SpecialName) hoặc mẹo nhỏ khác có thể được sử dụng?

  2. C#/VB.NET có tự phát ra các trình khởi tạo này cho một số mục đích không? Từ những gì tôi đã nhìn thấy chúng được sử dụng bởi quản lý C + + cho một số mục đích interop, nhưng tôi không thể tìm thấy bất kỳ tài liệu tham khảo cho họ đang được sử dụng cho các mục đích khác. Bất kỳ ý tưởng?

+1

Bạn có thể sử dụng một kỹ thuật tương tự cho [Thư viện Melody không bị giới hạn của Jon Skeet] (http://code.google.com/p/unconstrained-melody/), mà anh ta sử dụng để tránh xung quanh thực tế là bạn không thể sử dụng enum ràng buộc trong C#. Giải pháp của ông là sử dụng các thuộc tính giữ chỗ để thúc đẩy một chương trình hậu xử lý (được viết bằng C#) để điều khiển ilasm.exe viết lại IL để thực hiện chính xác những thứ không thể được thực hiện trong C#. –

+0

Thảo luận liên quan: http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx – user423430

Trả lời

8

Không, không có cách nào phát ra chúng trong C#, vì C# đặt mọi thứ trong lớp/cấu trúc và trình khởi tạo mô-đun cần phải toàn cục.

Bạn sẽ phải sử dụng một công cụ khác để viết chúng, tốt nhất là IL-Assembler. Đối với câu hỏi thứ hai, tôi phải thừa nhận rằng tôi không biết, nhưng tôi chưa bao giờ thấy bất kỳ được tạo ra bởi C#, và tôi sử dụng ILDasm khá thường xuyên, vì vậy tôi giả định rằng nó không phát ra chúng.

-5

Nếu bạn có các hàm tạo tĩnh hoặc các lớp singleton mà bạn có thể truy cập đúng một biến tĩnh, trình biên dịch C# sẽ phát ra .cctor.

+1

Nó phát ra a .cctor trong lớp mà bạn đã định nghĩa một hàm tạo tĩnh, có, nhưng đó chỉ là hàm tạo tĩnh của lớp đó và sẽ chạy lần đầu tiên lớp được truy cập. Trình khởi tạo mô-đun là một .cctor trên lớp giả và được bảo đảm chạy trước bất kỳ mã nào khác trong hội đồng, bất kể mã nào được truy cập trước. –

3

Có thể System.Reflection.Emit không gian tên có thể giúp bạn. MethodAttributes liệt kê có chứa các yếu tố tương tự (SpecialName, RTSpecialName).

10

Kiểm tra các addon mô-đun initializer của tuyệt vời opensource dự án IL-Weaver "fody", được viết bởi Simone Cropp: https://github.com/fody/moduleinit

Nó cho phép bạn chỉ định một phương pháp mà sẽ được dịch sang một initializer lắp ráp bởi fody:

public static class ModuleInitializer 
{ 
    public static void Initialize() 
    { 
     //Init code 
    } 
} 

bị này:

static <Module>() 
{ 
    ModuleInitializer.Initialize(); 
} 
+5

Cảm ơn bạn đã đề xuất. Điều đó thực sự dựa trên mã của riêng tôi mà tôi đã viết sau khi đặt câu hỏi này. Simon Cropp sau đó điều chỉnh nó như là một plugin cho dự án Fody tuyệt vời của mình. –

1

Einar, questi của bạn trên đã không làm cho rõ ràng với tôi rằng bạn đã viết một công cụ cho phép để tiêm một bộ khởi tạo mô-đun vào một hội đã được biên dịch.

http://einaregilsson.com/module-initializers-in-csharp

Tôi đã thử ứng dụng của bạn và ứng dụng hoạt động hoàn hảo. Khi bạn viết nó sẽ làm việc với tất cả các khuôn khổ hiện tại từ 2 đến 4.5.

Chỉ có một vấn đề khiến giải pháp của bạn vô dụng đối với tôi: Trình khởi tạo của bạn được gọi khi ứng dụng lần đầu tiên TRUY CẬP bất kỳ thứ gì trong hội đồng.

Điều tôi cần là trình khởi tạo mô-đun sẽ được gọi ngay lập tức khi Assembly được nạp vào tiến trình. Nhưng nó không phải như vậy. Vì vậy, nếu ứng dụng không truy cập vào assembly, nó sẽ không bao giờ được khởi tạo.

Sau khi điều tra cả ngày, có vẻ như với tôi rằng cách duy nhất để có được điều này là viết một hội đồng quản trị C++ và thực thi mã trong DllMain().

+0

Các assembly .NET thường được tải chậm trễ. Có nghĩa là: giả định của bạn rằng khởi tạo mô-đun được thực hiện một thời gian sau khi lắp ráp được nạp có lẽ là không đúng sự thật. Nó chỉ là lắp ráp chỉ được nạp khi nó cần thiết, * không * ngay lập tức khi ứng dụng bắt đầu. –

+0

Có lẽ tôi không đủ rõ ràng. Tôi đang nói về tải một C# DLL vào một quá trình C# thông qua Assembly.Load(). Trong trường hợp này, bộ khởi tạo không được thực hiện. Tôi đã tìm kiếm một tương đương cho DllMain() trong C++ được thực thi ngay lập tức khi DLL được nạp vào trong tiến trình. – Elmue

+0

Ah, tôi hiểu rồi. Lạ thật rồi. –