2013-01-03 68 views
5

Tôi đã tạo một công cụ lấy trong các plugin của bên thứ ba (DLL) thực hiện giao diện.Có thể tạo một thể hiện của một lớp mà không cần chạy bất kỳ mã nào từ lớp không? (không có ctor, không có khởi tạo trường)

Vì tôi không kiểm soát mã được cắm vào, tôi muốn có thể chạy 1 phương thức cụ thể (từ giao diện) từ lớp chính xác (vòng lặp GetTypes cho đến khi tôi tìm lớp giao tiếp).

Kể từ khi bất cứ ai có thể tạo mã constructor đẹp thực thi trên Activator.CreateInstance, tôi có thể giải quyết điều đó bằng cách sử dụng FormatterServices.GetUninitializedObject. Nhưng điều đó không giúp khi mã đang được khởi tạo trên các trường trong lớp.

public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 

    //I only want this run. 
    public string MyProperty{ 
    get { 
     return "ANiceConstString"; 
    } 
    } 
} 

Vấn đề với cả hai cách (CreateInstance/GetUninitializedObject) là các nhà xây dựng của someotherclass sẽ được chạy.

Trước khi bạn bắt đầu phân tích nhu cầu của mình. Điều này chỉ chạy trong khởi tạo của động cơ để có được một tập hợp các giá trị tiêu chuẩn. Nếu get'er này dựa vào các giá trị được khởi tạo khác, "plugin" sẽ được đánh dấu là không thành công vì không có giá trị hợp lệ nào được trả về. Nếu không được đánh dấu là không thành công, sau này lớp học sẽ được tải đúng với Activator.CreateInstance().

Vì vậy, hãy gắn bó với câu hỏi này: .Net có hỗ trợ bất kỳ cách nào để tạo lớp không được khởi tạo 100% không?

Cập nhật câu trả lời. Tôi đã thử nghiệm điều này trước khi tôi đăng câu hỏi của mình.

Đối với câu trả lời rằng someotherclass sẽ không chạy, tôi đã kiểm tra và chạy nó nếu tĩnh.

public class myclass : myinterface { 

    static Tutle test; 

    public myclass() { 
     test = new Tutle(); 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance hiển thị hộp thư. GetUninitializedObject không.

public class myclass : myinterface { 

    static Tutle test = new Tutle(); 

    public myclass() { 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance hiển thị hộp thư. GetUninitializedObject hiển thị hộp thông báo.

Có cách nào để có được xung quanh các bộ phận intializers và ctors tĩnh?

+0

Nếu bạn không thực sự muốn có một trường hợp đối tượng được tạo ra, có vẻ như bạn muốn có một * tĩnh * tài sản thay thế. Có, điều đó có nghĩa là bạn không thể chỉ định nó trong giao diện ... nhưng bạn đã sử dụng sự phản chiếu, vì vậy bạn có thể kiểm tra xem tất cả các loại có thuộc tính có liên quan hay không. Hoặc nếu bạn biết rằng giá trị thuộc tính phải luôn là hằng số, có thể yêu cầu thuộc tính tùy chỉnh thay thế. –

+2

Bất cứ khi nào bạn không có quyền kiểm soát mã được thực hiện, bạn có thể xem xét việc thực thi mã đó trong một AppDomain riêng biệt với các quyền hạn chế. Điều này có thể là một thay thế cho việc tạo ra một đối tượng uninitialized. –

Trả lời

14

Đơn giản chỉ cần:

var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass)); 

Đó sẽ không chạy initializers constructor/lĩnh vực. Ở tất cả. Nó sẽ không chạy hàm tạo cho someotherclass; name sẽ là null.

Tuy nhiên, sẽ thực thi bất kỳ công cụ xây dựng tĩnh tĩnh nào tồn tại, nếu cần theo quy tắc .NET chuẩn.

BAO GIỜ! Tôi nên lưu ý rằng phương pháp này không dành cho việc sử dụng đặc biệt; mục đích chính của nó là để sử dụng trong serializers và remoting engines. Có một cơ hội rất tốt là các loại sẽ không hoạt động chính xác nếu được tạo theo cách này, nếu bạn không thực hiện các bước sau để đưa chúng trở lại trạng thái hợp lệ (bất kỳ công cụ nối tiếp/từ xa nào chắc chắn sẽ làm).

+1

Đúng, bộ khởi tạo trường ('public someotherclass name = new someotherclass();' trong ví dụ của bạn) sẽ * không * được thực hiện. –

+0

Kiểm tra cập nhật của tôi. GetUninitializedObject chạy mã ... Tất cả đã được kiểm tra trước khi đăng. NM. Tĩnh là vấn đề. Vì vậy, không có cách nào để có được xung quanh tĩnh sau đó? – Wolf5

+1

@ Wolf5 Tôi đã thử nghiệm quá, p và không: không phải là (chỉnh sửa: nhận xét này đã lỗi thời vì bây giờ nó đã được đánh dấu là 'tĩnh') –

5

Như một yếu tố thiết kế thay thế:

[SomeFeature("ANiceConstString")] 
public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 
} 

Bây giờ bạn có thể truy cập các tính năng mà không instantiation; chỉ cần sử dụng:

var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
    type, typeof(SomeFeatureAttribute)); 
string whatever = attrib == null ? null : attrib.Name; 

với:

[AttributeUsage(
    AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)] 
public sealed class SomeFeatureAttribute : Attribute 
{ 
    private readonly string name; 
    public string Name { get { return name; } } 
    public SomeFeatureAttribute(string name) { this.name = name; } 
} 
+0

Cảm ơn. Tôi nghĩ tôi sẽ thêm nó. Khi giao diện được xuất bản và thiết lập, tôi có thể thực hiện kiểm tra lại nếu thuộc tính được thiết lập và sử dụng nó trước khi tạo một cá thể. Khả năng tương thích ngược. – Wolf5

+0

Tôi thích điều này tốt hơn nhiều. Âm thanh 'GetUninitializedObject' rất nguy hiểm! –

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