2010-10-01 15 views
5

क्या कॉल स्टैक से स्पष्ट इंटरफ़ेस कार्यान्वयन पर प्रतिबिंबित करना संभव है? मैं इंटरफेस पर एक विशेषता देखने के लिए इस जानकारी का उपयोग करना चाहता हूं।कॉल स्टैक से सी # स्पष्ट इंटरफ़ेस कार्यान्वयन पर कैसे प्रतिबिंबित करें?

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.??? 
    } 
} 

विशेष रूप से, ट्रेस में(), मैं चाहते हैं method से typeof(IFoo) को पाने के लिए सक्षम होने के लिए:

इस कोड को देखते हुए।

घड़ी विंडो में, यदि मैं method.ToString() पर देखता हूं तो यह मुझे Void InterfaceReflection.IFoo.Test() (इंटरफेस रिफ्लेक्शन मेरी असेंबली का नाम देता है) देता है।

मैं वहां से typeof(IFoo) कैसे प्राप्त कर सकता हूं? क्या मुझे असेंबली से नाम-आधारित प्रकार लुकअप का उपयोग करना चाहिए, या में Type IFoo कहीं छिपा हुआ है?

अद्यतन: 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 करने के लिए

यहाँ अंतिम समाधान है, धन्यवाद को लागू करने के लिए विधि इंटरफ़ेस प्रकार होगा। यह केवल स्पष्ट इंटरफ़ेस कार्यान्वयन के साथ काम करेगा, लेकिन यह वही है जो मुझे चाहिए। अब मैं वास्तविक इंटरफ़ेस प्रकार से जुड़े गुणों की क्वेरी के लिए itype का उपयोग कर सकता हूं।

उनकी मदद के लिए सभी को धन्यवाद।

उत्तर

3

वीएस -2010 के साथ परीक्षण करते हुए, मुझे डेक्लिंगिंग टाइप टाइप किया गया, जिसमें ऑब्जेक्ट प्रकार होता है जिसमें विधि होती है, जहां से आप टाइप ऑब्जेक्ट्स के रूप में इंटरफेस प्राप्त कर सकते हैं।

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); 
     } 
    } 

रिटर्न:

TestConsole.Foo 
TestConsole.IFoo 

+0

आह! यही वह है, धन्यवाद। मैं केवल गुणों को देख रहा था, और तरीकों को देखने के लिए नहीं सोचा था। मुझे लगता है कि 'GetInterfaces()' मैं उपयोग कर सकता हूं। मैं 'method.Name' का उपयोग करूंगा जो मुझे' InterfaceReflection.IFoo.Test' देता है, मैं "IFoo" निकाल दूंगा, और इसके मिलान प्रकार को खोजने के लिए 'GetInterface() 'का उपयोग करूंगा। यह काम करता है। – scobi

+0

यदि फू ने 1 से अधिक इंटरफ़ेस लागू किए हैं, तो आपको अभी भी यह पता लगाना होगा कि कौन सी विधि संबंधित है ... प्लस क्या होगा यदि इंटरफ़ेस में टेस्ट को परिभाषित नहीं किया गया था, और फ़ू का वास्तविक तरीका था? – CodingWithSpike

+0

@ रैली25rs: आप i.GetMethods() चला सकते हैं और GetFrame (0) के परिणाम के खिलाफ मैच कर सकते हैं। GetMethod() – Kyte

0

मैं बहुत अधिक अनुमान नहीं लेना चाहता हूं, लेकिन इस मामले में, ऐसा लगता है कि आप कुछ भ्रम पैदा कर सकते हैं क्योंकि फू और प्रोग्राम अंतर-निर्भर हैं। आम तौर पर, मुझे लगता है कि प्रोग्राम "स्वयं" कार्यक्रम (जो प्रोग्राम का अज्ञेयवादी होगा) इस तरह से होगा कि प्रतिनिधि को स्थापित करने के लिए यह ज़िम्मेदार है, इसलिए प्रतिबिंब से बचा जा सकता है ... जिस तरह से आपने इसे स्थापित किया है, फू "मालिक "(वास्तव में, मुझे लगता है कि यह संभवतः अधिक सटीक है) कार्यक्रम एक तरह से (क्योंकि यह हार्डकॉइंग ए प्रोग्राम को अपने प्रोग्राम पर कॉल करता है।()), और प्रोग्राम" मालिक "का मालिक है (क्योंकि यह उदाहरण को नियंत्रित करता है)।

मुझे नहीं पता कि यह आपके विशेष स्केनेरियो में काम करेगा या नहीं, लेकिन ऐसा लगता है कि एक ईवेंट प्रकार का ऑपरेशन अधिक समझ में आता है और संचार को अधिक आसानी से संभाल सकता है।

अनुमानित समय कोड का नमूना:

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) 
     { 
      //... 
     } 
    } 
} 

मैं अपने प्रश्न है, हालांकि गलतफहमी हो सकती है।

+0

आप निश्चित रूप से गलत समझ रहे हैं मेरा प्रश्न। :) यह सबसे सरल तरीके से प्रश्न पूछने के उद्देश्य से पूरी तरह से एक संक्षिप्त उदाहरण है। मुझे वास्तव में दिलचस्पी है (ए) प्रतिबिंब सही कैसे प्राप्त करें और (बी) यह InterfaceReflection.exe व्यवसाय क्या है। यह सवाल वास्तुशिल्प डिजाइन के बारे में नहीं है। – scobi

2

methodSystem.Reflection.RuntimeMethodInfo होगा, जो System.Reflect.MethodBase से प्राप्त कक्षा है। आप उदा। उस पर Invoke() पर कॉल करें (यद्यपि यदि आपने इसे उस बिंदु पर किया जहां आपने इसे प्राप्त किया था, तो इसके परिणामस्वरूप अनंत असंतोष हो जाएगा जो अंततः ढेर को बहने से मर जाता है)।

ToString() पर कॉल करने पर यह पूरी तरह से योग्य नाम देता है। क्या आपने प्रोजेक्ट इंटरफेस रिफ्लेक्शन को कॉल किया था?

यह सुनिश्चित नहीं है कि आप उससे अधिक क्या चाहते हैं।

संपादित करें: ठीक है, अब मैं करता हूं।घोषणा प्रकार को खोजने के लिए DeclaringType प्रॉपर्टी को देखने के लिए, यह उस वर्ग को वापस कर देगा जिस पर विधि घोषित की गई थी (जिसे वह वर्ग कहा जा सकता था, या बेस क्लास):

अभी तक इतना आसान, यह रिटर्न फू के लिए एक प्रकार वस्तु।

अब मुश्किल बिट के लिए, क्योंकि आप जिस इंटरफ़ेस पर घोषित किए गए थे, उसकी परवाह करते हैं। हालांकि, एक से अधिक इंटरफेस हो सकते हैं जो एक ही हस्ताक्षर के साथ एक विधि को परिभाषित करते हैं, जिसका मतलब है कि सरल सवाल "यदि यह एक इंटरफ़ेस से आया, तो वह इंटरफ़ेस क्या था?" हमेशा एक जवाब नहीं है।

यह करने के लिए एक neater तरीका नहीं हो सकता है, लेकिन सभी मैं के बारे में सोच सकते हैं Type वस्तु आप DeclaringType से मिल गया पर GetInterfaces() बुला रहा है, और फिर एक जिसका नाम विधि के हस्ताक्षर से मेल खाता है की तलाश में।

+0

वाह। गलत कहने के बाद पछतावा करना। मैंने वास्तव में परियोजना इंटरफ़ेस रिफ्लेक्शन को कॉल किया था और इसके बारे में भूल गया था। मैं सोच रहा था कि यह एक आंतरिक .NET नाम था। ठीक है, मैं सवाल अपडेट कर दूंगा। मुझे अभी भी सही इंटरफेस प्रकार खोजने की समस्या है। – scobi

+0

@ स्कॉट बिलास ठीक है, तदनुसार मेरा जवाब अपडेट किया है। –

0

(मैं परियोजना TestConsole कहा जाता है) मैं नेट MethodInfo.Name संपत्ति के सामने से पूरा नाम संलग्न कर देता है इतना है कि यह एक अनूठा है लगता है प्रत्येक विधि के लिए नाम। के बारे में सोचो:

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

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

इस मामले में, typeof(Foo).GetMethods() दोनों Test() तरीकों वापसी होगी लेकिन उनके नाम का विरोध होगा, इसलिए मुझे लगता है कि वे उन्हें अद्वितीय बनाने के लिए इंटरफ़ेस नाम जोड़े जाते?

MethodInfo.DeclaringType कार्यान्वयन वाले प्रकार को लौटाता है। तो अगर IFoo वास्तव में एक इंटरफेस के बजाय कुछ आधार प्रकार थे, और वहां एक आधार विधि घोषणा थी, तो .DeclaringType बेस क्लास के प्रकार को वापस कर देगा।

दिलचस्प है, मैं MethodInfo में कहीं भी या तो वास्तविक इंटरफ़ेस नाम खोजने के लिए नहीं कर पा रहे हैं, इसलिए मुझे लगता है कि आप नाम से उसे ढूंढने की है, कुछ की तरह:

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. 
     } 
    } 
संबंधित मुद्दे