2010-01-14 13 views
11

एक बुलाया विधि पैरामीटर प्रकार/इस तरह की जानकारी की गणना कर सकते हैं:कैसे पारित कर की गणना करने में विधि पैरामीटर

private void SomeMethod(int thisValue, string thatValue) 
{ 
    StackTrace stackTrace = new StackTrace(); 
    foreach (ParameterInfo pInfo in stackTrace.GetFrame(0).GetMethod().GetParameters()) 
    { 
    string name = pInfo.Name; 
    string type = pInfo.GetType().ToString(); 
    } 
} 

लेकिन वहाँ किसी भी तरह से प्रत्येक पैरामीटर की वास्तविक वस्तु प्राप्त करने के लिए है?

EDIT: मेरा लक्ष्य सभी मानकों को गिनना और उनके मूल्य प्राप्त करना है। LinQ भाव का उपयोग करना, एक तो जैसे पैरामीटर मान प्राप्त कर सकते हैं:

private void SomeMethod(int thisValue, string thatValue) 
{ 
    object valueOfThis = GetParameterValue(() => thisValue); 
    object valueOfThat = GetParameterValue(() => thatValue); 
} 
private object GetParameterValue<T>(Expression<Func<T>> expr) 
{ 
    var body = ((MemberExpression)expr.Body); 
    return ((FieldInfo)body.Member).GetValue(((ConstantExpression)body.Expression).Value); 
} 

लेकिन मुझे क्या करना चाहते हैं की तरह कुछ है:

foreach (fooObject o in thisMethod.GetParameterObjects()) 
{ 
    object someValue = GetParameterValue(() => fooObject); 
} 

और जिससे संग्रह के लिए एक सामान्य विधि सभी मापदंडों है और उनके मूल्य

+0

क्या आप वास्तविक पैरामीटर मान वाले स्टैक ट्रेस बनाने की कोशिश कर रहे हैं? –

+1

Uhm, वास्तविक पैरामीटर उदाहरणों विधि ... –

+1

@Mark में सही कर रहे हैं: मेरे विचार भी है, लेकिन देखना है कि यह स्पष्ट है वह कुछ अधिक सामान्य, कुछ है कि आप किसी भी ढेर फ्रेम के मूल्यों को प्राप्त करने की अनुमति होगी (के लिए देख रहा है मैं अनुमान लगा रहा हूं ...) –

उत्तर

9

अद्यतन:

सब कुछ समझाने के लिए कोशिश कर रहा द्वारा मैं "overcomplicated" प्रारंभिक जवाब की तरह लग रहा। उत्तर का संक्षिप्त संस्करण यहां दिया गया है।

private static void SomeMethod(int thisValue, string thatValue) 
{ 
    IEnumerable<object> parameters = GetParameters(() => SomeMethod(thisValue, thatValue)); 
    foreach (var p in parameters) 
     Console.WriteLine(p); 
} 
private static IEnumerable<object> GetParameters(Expression<Action> expr) 
{ 
    var body = (MethodCallExpression)expr.Body; 
    foreach (MemberExpression a in body.Arguments) 
    { 
     var test = ((FieldInfo)a.Member).GetValue(((ConstantExpression)a.Expression).Value); 
     yield return test; 
    } 
} 

और यहां कुछ स्पष्टीकरण के साथ लंबा संस्करण है।

वास्तव में, यदि आप अभिव्यक्ति के पेड़ का उपयोग करें, आप इसके मापदंडों की गणना करने के लिए एक विधि के अंदर होने की जरूरत नहीं है।

static void Main(string[] args) 
    { 

     // First approach. 
     IEnumerable<object> parameters = GetParametersFromConstants(() => SomeMethod(0, "zero")); 
     foreach (var p in parameters) 
      Console.WriteLine(p); 

     // Second approach. 
     int thisValue = 0; 
     string thatValue = "zero"; 
     IEnumerable<object> parameters2 = GetParametersFromVariables(() => SomeMethod(thisValue, thatValue)); 
     foreach (var p in parameters2) 
      Console.WriteLine(p); 

     Console.ReadLine(); 
    } 

    private static void SomeMethod(int thisValue, string thatValue) 
    { 
     Console.WriteLine(thisValue + " " + thatValue); 
    }  

    private static IEnumerable<object> GetParametersFromVariables(Expression<Action> expr) 
    { 
     var body = (MethodCallExpression)expr.Body; 
     foreach (MemberExpression a in body.Arguments) 
     {    
      var test = ((FieldInfo)a.Member).GetValue(((ConstantExpression)a.Expression).Value); 
      yield return test; 
     } 
    } 

    private static IEnumerable<object> GetParametersFromConstants(Expression<Action> expr) 
    { 
     var body = (MethodCallExpression)expr.Body; 
     foreach (ConstantExpression a in body.Arguments) 
     { 
      var test = a.Value; 
      yield return test; 
     } 
    } 

} 

नोट, कि यदि आप अभिव्यक्ति पेड़ों का उपयोग करते हैं, तो आपका कोड विधि को पारित अभिव्यक्ति पर बहुत निर्भर करता है। मैंने एक स्थिरांक का उपयोग कर एक और एक चर का उपयोग कर दिखाया है। लेकिन निश्चित रूप से और अधिक परिदृश्य हो सकते हैं। आप दोनों मामलों के लिए एक विधि का उपयोग करने के लिए इस कोड को दोबारा कर सकते हैं, लेकिन मैंने फैसला किया कि समस्या इस तरह से बेहतर तरीके से दिखाती है।

+0

उत्तर के लिए धन्यवाद। हालांकि, मैं कुछ ऐसा ढूंढ रहा था जिसे इसे सामान्य बनाने के लिए SomeMethod() के अंदर रखा जा सकता है। आपके द्वारा प्रदान किया गया उदाहरण SomeMethod() से पहले कस्टम कोड को कॉल करने के लिए मजबूर करता है। –

+0

नहीं, आपको SomeMethod से पहले कुछ भी कॉल करने की आवश्यकता नहीं है। "दूसरा दृष्टिकोण" के रूप में चिह्नित कोड लें (केवल वेरिएबल्स घोषणा और प्रारंभिकता को छोड़ें) और इसे विधि में पेस्ट करें। आपको विधि के अंदर पैरामीटर गणना मिलेगी। मैं सिर्फ यह इंगित करना चाहता था कि आप इसे कहीं से भी कर सकते हैं, जरूरी नहीं कि विधि निकाय से। –

+0

यदि आपको किसी भी तरह से स्रोत कोड में पैरामीटर सूचीबद्ध करना है, तो 'GetParameters' को परेशान क्यों करें? यह करेगा: 'ऑब्जेक्ट [] पैरा = नई ऑब्जेक्ट [] {thisValue, thatValue}; ' –

1

ठीक है, तो यह सौदा है।

आप ऐसा नहीं कर सकते हैं, प्रबंधित भाषा से नहीं। मैं नहीं देखता कि कैसे कोई आपको स्टैक फ्रेम पर नियंत्रण रखने की अनुमति देगा। और एक तरह से आप यही चाहते हैं। क्योंकि आपको मूल्य प्राप्त करने के लिए जानकारी चाहिए।

अब रन-टाइम यह जानता है, इसमें सभी जानकारी है, लेकिन आप यह नहीं मान सकते कि यह एक स्टैक फ्रेम बनाने के बारे में कैसे होगा, क्योंकि आप ऐसा करने के लिए नहीं हैं।

एर्गो, इसके बारे में जाने का एकमात्र तरीका है। प्रोफाइलिंग एपीआई।

मैं here समाप्त करता हूं। प्रोफाइलिंग एपीआई के कार्यों के भीतर। मैं शर्त लगाता हूं कि ऐसा करने का एक तरीका है कि आप प्रबंधित कोड से एक अप्रबंधित वर्ग का आह्वान करके पैरामीटर मानों में खोदने दें।

अब, मैं ऐसा नहीं करूँगा क्योंकि पहले से ही बहुत सारे प्रोफाइलिंग उपकरण हैं, जेटब्रेन डॉटट्रेस एक नाम और वीएस -2010 में इंटेलिटेस के साथ इन सभी सिरदर्दों को आसानी से दूर कर दिया जाएगा ... IntelliTrace आपको डिबगिंग यात्रा करने का समय देगा।

ऐसा करने का दूसरा और स्पष्ट तरीका पूरी तरह से foobar है, लेकिन प्रयोग करने के लिए मजेदार अंत हो सकता है, यह हमेशा इस तरह से किया जा सकता है, लेकिन मैं अपने जीवन में कभी भी इस कोड को उत्पादन वातावरण में नहीं डालूंगा।

// compile with unsafe 
unsafe 
{ 
    var p = stackalloc int[1]; 
    var baseAddr = p - sizeof(int); 
} 

अब, आप baseAddr लिए नहीं लिख सकते हैं, लेकिन आप इसे पढ़ने के लिए अनुमति दी जानी चाहिए। मुश्किल हिस्सा स्टैक फ्रेमों को समझना है और इसे कॉलिंग सम्मेलन के साथ करना है और आपको कुछ समय के लिए निश्चित रूप से पता होना चाहिए। Here's उस सामान का एक रन डाउन और यह फास्टकॉल है।

इस जानकारी और पैरामीटरइन्फो वस्तुओं के साथ आप तर्कों के माध्यम से अपना रास्ता चलने में सक्षम होना चाहिए।

चूंकि आप कच्चे पॉइंटर्स के साथ काम करेंगे क्योंकि आपको उन्हें प्रबंधित वस्तुओं में बनाना होगा, और इसके लिए class है।

वहां आप जाते हैं, पागल हो जाओ!

के बावजूद एक बड़ी चेतावनी, आप स्टैक पर चलने के दौरान क्या पाएंगे, आप जो उम्मीद करेंगे, वह नहीं होगा। चूंकि रजिस्ट्रारों में तर्क रखा जा सकता है और रजिस्टरों को प्रबंधित कोड से एक्सेस नहीं किया जा सकता है।

1

आप MethodInfo.GetCurrentMethod().GetParameters() का उपयोग विधि मानकों की एक सूची प्राप्त कर सकते हैं। लेकिन प्रतिबिंब द्वारा अपने मूल्य प्राप्त करना असंभव है।

+1

@ मेहदी। हां, GetParameters() विधि पहले से ही मेरे प्रश्न में कवर किया गया था, धन्यवाद। –

संबंधित मुद्दे