2010-10-01 32 views
5

Có thể phản ánh về việc triển khai giao diện rõ ràng từ ngăn xếp cuộc gọi không? Tôi muốn sử dụng thông tin này để tra cứu một thuộc tính trên chính giao diện.Làm thế nào để phản ánh trên C# thực hiện giao diện rõ ràng từ ngăn xếp cuộc gọi?

Với mã này:

interface IFoo 
{ 
    void Test();  
} 

class Foo : IFoo 
{ 
    void IFoo.Test() { Program.Trace(); } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IFoo f = new Foo(); 
     f.Test(); 
    } 

    public static void Trace() 
    { 
     var method = new StackTrace(1, false).GetFrame(0).GetMethod(); 
     // method.??? 
    } 
} 

Cụ thể, trong Trace(), tôi muốn để có thể có được để typeof(IFoo) từ method.

Trong cửa sổ xem, nếu tôi nhìn vào method.ToString(), nó cung cấp cho tôi Void InterfaceReflection.IFoo.Test() (InterfaceReflection là tên của hội đồng của tôi).

Làm cách nào để truy cập vào số typeof(IFoo) từ đó? Tôi có phải sử dụng tra cứu kiểu dựa trên tên từ bản thân hội đồng hoặc có một số Type IFoo ẩn ở đâu đó trong số MethodBase không?

UPDATE:

Dưới đây là giải pháp cuối cùng, nhờ vào Kyte

public static void Trace() 
{ 
    var method = new StackTrace(1, false).GetFrame(0).GetMethod(); 
    var parts = method.Name.Split('.'); 
    var iname = parts[parts.Length - 2]; 
    var itype = method.DeclaringType.GetInterface(iname); 
} 

itype sẽ có các loại giao diện cho phương pháp thực hiện. Điều này sẽ chỉ làm việc với việc triển khai giao diện rõ ràng, nhưng đó chính xác là những gì tôi cần. Bây giờ tôi có thể sử dụng itype để truy vấn các thuộc tính gắn liền với loại giao diện thực tế.

Nhờ mọi người giúp đỡ.

Trả lời

3

Kiểm tra xung quanh với VS2010, tôi tìm thấy DeclaringType, là kiểu đối tượng có chứa phương thức, từ đó bạn có thể nhận các giao diện dưới dạng đối tượng Kiểu.

public static void Trace() { 
     var stack = new StackTrace(1, true); 
     var frame = stack.GetFrame(0); 
     var method = frame.GetMethod(); 

     var type = method.DeclaringType; 

     Console.WriteLine(type); 
     foreach (var i in type.GetInterfaces()) { 
      Console.WriteLine(i); 
     } 
    } 

Returns:

TestConsole.Foo 
TestConsole.IFoo 

(tôi gọi là dự án TestConsole)

+0

Ah! Đó là nó, cảm ơn bạn. Tôi chỉ nhìn vào các thuộc tính, và không nghĩ xem xét các phương pháp. Tôi nghĩ 'GetInterfaces()' là những gì tôi có thể sử dụng. Tôi sẽ sử dụng 'method.Name' cho tôi' InterfaceReflection.IFoo.Test', tôi sẽ kéo ra "IFoo" và sử dụng 'GetInterface()' để tìm kiểu kết hợp của nó. Điều đó hoạt động. – scobi

+0

Nếu Foo triển khai hơn 1 giao diện, thì bạn vẫn sẽ phải tìm ra phương thức nào thuộc về ... Cộng với những gì nếu Kiểm tra không được xác định trong Giao diện và là phương pháp thực tế của Foo? – CodingWithSpike

+0

@ rally25rs: Bạn có thể chạy i.GetMethods() và khớp với kết quả của GetFrame (0) .GetMethod() – Kyte

0

Tôi không muốn đoán quá nhiều, nhưng trong trường hợp này, có vẻ như bạn có thể gây nhầm lẫn vì Foo và Chương trình phụ thuộc lẫn nhau. Thông thường, tôi sẽ nghĩ rằng chương trình sẽ "sở hữu" Foo (mà sẽ là bất khả tri của Chương trình) theo cách nó có trách nhiệm thiết lập đại biểu để phản ánh có thể tránh được ... cách bạn thiết lập, Foo "sở hữu "(thực sự, tôi đoán phụ thuộc vào có lẽ chính xác hơn) Chương trình theo một cách (bởi vì nó hardcoing aa gọi đến Program.Trace()) của nó, và Chương trình" sở hữu "Foo một cách (vì nó kiểm soát các trường hợp).

Tôi không biết điều này có hiệu quả trong scenerio cụ thể của bạn hay không, nhưng có vẻ như thao tác loại sự kiện có thể có ý nghĩa hơn và xử lý giao tiếp đơn giản hơn.

ETA: Mã mẫu:

public interface IFoo 
{ 
    event EventHandler Testing; 
    void Test(); 
} 
public class Foo : IFoo 
{ 
    public event EventHandler Testing; 
    protected void OnTesting(EventArgs e) 
    { 
     if (Testing != null) 
      Testing(this, e); 
    } 
    public void Test() 
    { 
     OnTesting(EventArgs.Empty); 
    } 
} 

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     IFoo f = new Foo(); 
     f.Testing += new EventHandler(f_Testing); 
     f.Test(); 
    } 

    static void f_Testing(object sender, EventArgs e) 
    { 
     IFoo foo = sender as IFoo; 
     if (foo != null) 
     { 
      //... 
     } 
    } 
} 

tôi có thể hiểu lầm câu hỏi của bạn, mặc dù.

+0

Bạn chắc chắn hiểu lầm câu hỏi của tôi. :) Đây là một ví dụ giả tạo chỉ nhằm mục đích đặt câu hỏi theo cách đơn giản nhất có thể. Tôi thực sự chỉ quan tâm đến (a) làm thế nào để có được sự phản ánh đúng và (b) những gì giao diện này InterfaceReflection.exe là về. Câu hỏi này không phải là về thiết kế kiến ​​trúc. – scobi

2

method sẽ là System.Reflection.RuntimeMethodInfo, là lớp có nguồn gốc từ System.Reflect.MethodBase. Bạn có thể ví dụ: gọi Invoke() trên đó (mặc dù nếu bạn đã làm như vậy tại điểm mà bạn có được nó, sau đó điều này sẽ dẫn đến một đệ quy vô hạn mà cuối cùng chết bằng cách tràn ngăn xếp).

Gọi ToString() trên đó trả về tên đầy đủ. Bạn đã gọi cho dự án InterfaceReflection chưa?

Không chắc chắn bạn muốn gì hơn thế.

Chỉnh sửa: OK, bây giờ tôi làm.Để tìm kiểu khai báo xem thuộc tính DeclaringType, điều này sẽ trả về lớp mà phương thức đã được khai báo (có thể là lớp mà nó được gọi là, hoặc một lớp cơ sở):

Cho đến nay rất dễ, điều này trả về một đối tượng Type cho Foo.

Bây giờ cho một chút khó khăn, bởi vì bạn quan tâm đến giao diện được khai báo. Tuy nhiên, có thể có nhiều hơn một giao diện xác định một phương thức có cùng chữ ký chính xác, có nghĩa là câu hỏi đơn giản "nếu điều này đến từ một giao diện, giao diện đó là gì?" không phải lúc nào cũng có một câu trả lời duy nhất.

Có thể có cách khác để thực hiện việc này, nhưng tất cả những gì tôi có thể nghĩ là gọi GetInterfaces() trên đối tượng Type bạn nhận được từ DeclaringType và sau đó tìm đối tượng có tên khớp với chữ ký của phương thức.

+0

Chà. Chân trong miệng. Tôi đã thực sự gọi đến dự án InterfaceReflection và quên nó đi. Tôi đã nghĩ đó là một tên .NET bên trong. Ok, tôi sẽ cập nhật câu hỏi. Tôi vẫn gặp sự cố khi tìm loại giao diện chính xác. – scobi

+0

@Scott Bilas okily, đã cập nhật câu trả lời của tôi cho phù hợp. –

0

tôi nghĩ .NET gắn thêm tên đầy đủ vào phía trước của tài sản MethodInfo.Name để nó có một độc đáo tên cho mỗi phương thức. Hãy suy nghĩ về:

interface IFoo 
{ 
    void Test(); 
} 
interface IFoo2 
{ 
    void Test(); 
} 

class Foo : IFoo, IFoo2 
{ 
    void IFoo.Test() { Trace(); } 
    void IFoo2.Test() { Trace(); } 
} 

Trong trường hợp này, typeof(Foo).GetMethods() sẽ trả lại cả hai phương pháp Test() nhưng tên của họ mâu thuẫn, vì vậy tôi đoán họ gắn tên giao diện để làm cho họ duy nhất?

MethodInfo.DeclaringType trả về loại chứa triển khai. Vì vậy, nếu IFoo thực sự là một số loại cơ sở thay vì một giao diện, và có một tuyên bố phương thức cơ sở ở đó, sau đó .DeclaringType sẽ trả về loại của lớp cơ sở.

Điều thú vị là, tôi dường như không thể tìm ra tên giao diện thực tế bất cứ nơi nào trong MethodInfo một trong hai, vì vậy tôi đoán bạn sẽ phải nhìn nó theo tên, một cái gì đó như:

public static void Trace() 
    { 
     var method = new System.Diagnostics.StackTrace(1, false).GetFrame(0).GetMethod(); 
     var fromType = method.DeclaringType; 
     if (method.Name.Contains(".")) 
     { 
      var iname = method.Name.Substring(0, method.Name.LastIndexOf('.')); 
      fromType = Type.GetType(iname); // fromType is now IFoo. 
     } 
    } 
Các vấn đề liên quan