আপনি বর্তমানে সম্পাদনকারী পদ্ধতির নাম জানতে প্রতিবিম্বটি ব্যবহার করতে পারেন?


202

মত শিরোনাম বলেছেন: প্রতিবিম্ব আপনি বর্তমান সম্পাদন পদ্ধতির নাম দিতে পারে।

হাইজেনবার্গ সমস্যার কারণে আমি অনুমান করতে চাইছি না। আপনি কীভাবে এমন একটি পদ্ধতি কল করবেন যা বর্তমান পদ্ধতিটি পরিবর্তন না করেই আপনাকে বর্তমান পদ্ধতিটি বলবে? তবে আমি আশা করছি সেখানে কেউ আমাকে ভুল প্রমাণ করতে পারে।

হালনাগাদ:

  • পার্ট 2: এটি কি কোনও সম্পত্তির অভ্যন্তরীণ কোডটি দেখতে ব্যবহার করা যেতে পারে?
  • পার্ট 3: পারফরম্যান্সটি কেমন হবে?

চূড়ান্ত
ফলাফলটি আমি মেথডবেস.গেটকন্টারমথোড () সম্পর্কে শিখেছি। আমি আরও শিখেছি যে আমি কেবল একটি স্ট্যাক ট্রেস তৈরি করতে পারি না, আমি চাইলে কেবল সঠিক ফ্রেমটি তৈরি করতে পারি।

এটি কোনও বৈশিষ্ট্যের অভ্যন্তরে ব্যবহার করতে, কেবলমাত্র 'সেট_' বা 'get_' অপসারণের জন্য একটি .Substring (4) নিন।


জোয়েল, আমি এটি একটি পুরানো প্রশ্ন জানি, কিন্তু একটি পদ্ধতির সঠিক ফ্রেম তৈরি করে আপনি কী বোঝাতে চাইছেন?
অভিজিৎ

এটি কল স্ট্যাকের কোনও নির্দিষ্ট আইটেমকে বোঝায়: স্ট্যাক ট্রেসের অংশটি গুরুত্বপূর্ণ।
জোয়েল কোহোর্ন

উত্তর:


119

.NET 4.5 হিসাবে আপনি [কলারেমবারনাম] ব্যবহার করতে পারেন

উদাহরণ: একটি সম্পত্তি সেটার (দ্বিতীয় অংশের উত্তর দিতে):

    protected void SetProperty<T>(T value, [CallerMemberName] string property = null)
    {
        this.propertyValues[property] = value;
        OnPropertyChanged(property);
    }

    public string SomeProperty
    {
        set { SetProperty(value); }
    }

সংকলকটি কলসাইটগুলিতে মেলানো স্ট্রিং লিটারেল সরবরাহ করবে, সুতরাং মূলত কোনও কার্য সম্পাদনের ওভারহেড নেই।


3
এটা অসাধারণ! আমি StackFrame(1)লগিংয়ের জন্য অন্যান্য উত্তরে বর্ণিত পদ্ধতিটি ব্যবহার করছিলাম , যা জিটারগুলি ইনলাইনিং জিনিসগুলি শুরু করার সিদ্ধান্ত না নেওয়া পর্যন্ত কাজ করবে বলে মনে হয়েছিল। পারফরম্যান্সের কারণে ইনলাইনিং প্রতিরোধ করার জন্য আমি বৈশিষ্ট্যটি যুক্ত করতে চাইনি। ব্যবহার [CallerMemberName]পদ্ধতির সমস্যা সমাধান করা হয়েছে। ধন্যবাদ!
ব্রায়ান রজার্স

5
[কলার মেম্বারনাম] বিসিএল বিল্ড প্যাক
ভেনসন

2
অ্যাকাউন্টে বিবেচনা করুন যে ডিবাগ মোডে স্ট্যাকফ্রেম (1) ব্যবহার করা উচিত। কম্পাইল করার সময় রিলিজ মোড ব্যবহার করার সময় কিছু অপ্টিমাইজেশন হতে পারে এবং স্ট্যাকটি আপনি যা প্রত্যাশা করেছিলেন তা নাও হতে পারে।
এক্সেল ও'কনেল

এটি কি বর্তমানে চালানো পদ্ধতির পরিবর্তে কলিং সদস্যকে (অর্থাত্ সাম্প্রোপার্টি) ফিরিয়ে দেবে না?
লেনার্ট

1
হ্যাঁ, সেটারটি চাওয়ার ফলে কল আসবে OnPropertyChanged("SomeProperty")এবং নাOnPropertyChanged("SetProperty")
জন নিলসন

189

অ- asyncপদ্ধতিগুলির জন্য কেউ ব্যবহার করতে পারে

System.Reflection.MethodBase.GetCurrentMethod().Name;

https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.getcurrentmethod

দয়া করে মনে রাখবেন যে asyncপদ্ধতিগুলির জন্য এটি "মুভনেেক্সট" ফিরে আসবে।


8
সচেতন থাকুন যে এটি সর্বদা প্রত্যাশিত ফলাফল দেয় না। উদাহরণস্বরূপ, ছোট পদ্ধতিগুলি বা বৈশিষ্ট্যগুলি প্রায়শই রিলিজ বিল্ডগুলিতে অন্তর্ভুক্ত থাকে, সেক্ষেত্রে ফলাফল পরিবর্তে কলারের পদ্ধতির নাম হবে।
আবেল

5
যতদূর আমি জানি, না। কারণ রানটাইমের সময়, এমএসআইএল এক্সিকিউশন পয়েন্টার (এটি জেআইটিড) থেকে আর পাওয়া যায় না। আপনি যদি পদ্ধতিটির নাম জানেন তবে আপনি প্রতিচ্ছবিটি ব্যবহার করতে পারেন। মুল বক্তব্যটি হ'ল, যখন ইনলাইন করা হয়েছে, বর্তমানে নির্বাহকারী পদ্ধতিটি এখন অন্য একটি পদ্ধতি (যেমন, স্ট্যাকটি এক বা একাধিক উচ্চতর)। অন্য কথায়, পদ্ধতিটি অদৃশ্য হয়ে গেল। এমনকি আপনি যদি আপনার পদ্ধতিটি নোইনলাইনিংয়ের সাথে চিহ্নিত করে রাখেন, তবুও এটি টেল-কলকে অনুকূলিত করার সুযোগ রয়েছে, এক্ষেত্রে এটি খুব বেশি চলে। এটি ডিবাগ বিল্ড করার সময়, যদিও কাজ করবে।
আবেল

1
ইনলাইন এড়ানোর জন্য পদ্ধতির শীর্ষে [মেথডিম্পল (মেথডিম্পলপশনস.নোইনলাইনিং)] বৈশিষ্ট্য যুক্ত করুন।
alex.peter

asyncপদ্ধতির অভ্যন্তরে আপনি সম্ভবত পদ্ধতির নাম হিসাবে "মুভনেসেক্সট" পাবেন।
ভিক্টর ইয়ারেমা

46

লেক্সের সরবরাহিত স্নিপেটটি কিছুটা দীর্ঘ ছিল, সুতরাং আমি গুরুত্বপূর্ণ অংশটি দেখিয়ে দিচ্ছি যেহেতু অন্য কেউ সঠিক কৌশলটি ব্যবহার করে নি:

string MethodName = new StackFrame(0).GetMethod().Name;

এটি মেথডবেস.গেটকোর্নামেথোড () নামটির কৌশলতে অভিন্ন ফলাফলগুলি ফিরিয়ে আনতে হবে তবে এটি এখনও উল্লেখ করার মতো because কারণ আমি এটি পূর্ববর্তী পদ্ধতির জন্য সূচক 1 ব্যবহার করে নিজের পদ্ধতিতে একবার প্রয়োগ করতে পেরেছিলাম এবং এটি বিভিন্ন সংখ্যক বৈশিষ্ট্য থেকে কল করতে পারি। এছাড়াও, এটি কেবল পুরো স্ট্যাকের সন্ধানের পরিবর্তে কেবল একটি ফ্রেম দেয়:

private string GetPropertyName()
{  //.SubString(4) strips the property prefix (get|set) from the name
    return new StackFrame(1).GetMethod().Name.Substring(4);
}

এটি ওয়ান লাইনারও;)


কোনও সহায়ক শ্রেণিতে পাবলিক স্ট্যাটিক স্ট্রিং গেটপোপার্টিনেম () হতে পারে? স্থির পদ্ধতি?
কিকিনেট

2
এড গুইন্সের উত্তরের মতো: রিলিজ বিল্ডে স্ট্যাকটি আলাদা হতে পারে এবং ইনলাইনিং বা লেজ কল অপ্টিমাইজেশানের ক্ষেত্রে প্রথম পদ্ধতিটি বর্তমান পদ্ধতির মতো নাও হতে পারে।
আবেল

আপনি যদি ব্যবহার করছেন তবে ইনলাইনিং ইস্যুটির চারপাশে সুন্দর উপায়ের জন্য জন নিলসনের উত্তর দেখুন et নেট .৪।
ব্রায়ান রজার্স

এটি গৃহীত উত্তর এবং উপরের উত্তরের চেয়েও ভাল হতে পারে
T.Todua

16

একটি খালি কনসোল প্রোগ্রামে মূল পদ্ধতির ভিতরে এটি ব্যবহার করে দেখুন:

MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);

কনসোল আউটপুট:
Main


12

হ্যাঁ অবশ্যই।

আপনি যদি কোনও জিনিস হেরফের করতে চান তবে আমি আসলে এই জাতীয় ক্রিয়াটি ব্যবহার করি:

public static T CreateWrapper<T>(Exception innerException, params object[] parameterValues) where T : Exception, new()
{
    if (parameterValues == null)
    {
        parameterValues = new object[0];
    }

    Exception exception   = null;
    StringBuilder builder = new StringBuilder();
    MethodBase method     = new StackFrame(2).GetMethod();
    ParameterInfo[] parameters = method.GetParameters();
    builder.AppendFormat(CultureInfo.InvariantCulture, ExceptionFormat, new object[] { method.DeclaringType.Name, method.Name });
    if ((parameters.Length > 0) || (parameterValues.Length > 0))
    {
        builder.Append(GetParameterList(parameters, parameterValues));
    }

    exception = (Exception)Activator.CreateInstance(typeof(T), new object[] { builder.ToString(), innerException });
    return (T)exception;
}

এই লাইন:

MethodBase method     = new StackFrame(2).GetMethod();

কলিং পদ্ধতিটি সন্ধানের জন্য স্ট্যাক ফ্রেমটিকে অনুসরণ করে তারপরে আমরা জেনেরিক ত্রুটি প্রতিবেদন করার জন্য এটিতে পরামিতি সম্পর্কিত তথ্য মানগুলি প্রতিবিম্ব ব্যবহার করি। বর্তমান পদ্ধতিটি পেতে কেবল পরিবর্তে বর্তমান স্ট্যাক ফ্রেম (1) ব্যবহার করুন।

অন্যরা যেমন বর্তমান পদ্ধতির নামের জন্য বলেছে আপনিও এটি ব্যবহার করতে পারেন:

MethodBase.GetCurrentMethod()

আমি স্ট্যাকটি হাঁটা পছন্দ করি কারণ যদি সেই পদ্ধতিতে অভ্যন্তরীণভাবে তাকান তবে এটি যেভাবেই স্ট্যাকক্রোলমার্ক তৈরি করে। স্ট্যাককে সম্বোধন করা আমার কাছে পরিষ্কার মনে হয় seems

৪.৫ পোস্ট করুন আপনি এখন পদ্ধতির নামের একটি স্ট্রিং পেতে পদ্ধতির পরামিতিগুলির অংশ হিসাবে [CallerMemberNameAttribute] ব্যবহার করতে পারেন - এটি কিছু পরিস্থিতিতে সহায়তা করতে পারে (তবে সত্যিই উপরে বর্ণিত উদাহরণটি বলে)

public void Foo ([CallerMemberName] string methodName = null)

এটি প্রধানত INotifyPropertyChanged সমর্থনের সমাধান বলে মনে হয়েছিল যেখানে এর আগে আপনি আপনার ইভেন্ট কোডের মাধ্যমে স্ট্রিংগুলি ছড়িয়ে দিয়েছিলেন।


বোকা নয়; আমি কেবল এগুলিতেই পাস করেছি probably আপনি এটি দেখতে আরও সহজ করার জন্য সম্ভবত কিছু করতে পারেন তবে অনুপাতের পুরষ্কারের চেষ্টাটিকে সহজ রাখার পক্ষে বলে মনে হয়েছিল। মূলত ডিভ কেবলমাত্র পদ্ধতি স্বাক্ষরের প্যারামিটার তালিকায় অনুলিপি করে (কোর্সের ধরণের অপসারণ)।
লেক্স

এটি কী: এক্সেপশন ফরমেট এবং গেটপ্যারামিটারলিস্ট?
কিকিনেট

উত্তরে দেরিতে তবে: এক্সপেশনফর্ম্যাটটি একটি ধ্রুব স্ট্রিং ফর্ম্যাট এবং গেটপ্যারামিটারলিস্ট একটি সাধারণ ফাংশন যা মানগুলির সাথে পরামিতিগুলিকে বিন্যাস করে (আপনি এই ইনলাইনটি করতে পারতেন)
লেক্স

11

পদ্ধতির নাম পাওয়ার উপায়গুলির সাথে তুলনা করা - লিনকপ্যাডে একটি নির্বিচারে সময় নির্মান ব্যবহার করে :

কোড

void Main()
{
    // from http://blogs.msdn.com/b/webdevelopertips/archive/2009/06/23/tip-83-did-you-know-you-can-get-the-name-of-the-calling-method-from-the-stack-using-reflection.aspx
    // and /programming/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-code

    var fn = new methods();

    fn.reflection().Dump("reflection");
    fn.stacktrace().Dump("stacktrace");
    fn.inlineconstant().Dump("inlineconstant");
    fn.constant().Dump("constant");
    fn.expr().Dump("expr");
    fn.exprmember().Dump("exprmember");
    fn.callermember().Dump("callermember");

    new Perf {
        { "reflection", n => fn.reflection() },
        { "stacktrace", n => fn.stacktrace() },
        { "inlineconstant", n => fn.inlineconstant() },
        { "constant", n => fn.constant() },
        { "expr", n => fn.expr() },
        { "exprmember", n => fn.exprmember() },
        { "callermember", n => fn.callermember() },
    }.Vs("Method name retrieval");
}

// Define other methods and classes here
class methods {
    public string reflection() {
        return System.Reflection.MethodBase.GetCurrentMethod().Name;
    }
    public string stacktrace() {
        return new StackTrace().GetFrame(0).GetMethod().Name;
    }
    public string inlineconstant() {
        return "inlineconstant";
    }
    const string CONSTANT_NAME = "constant";
    public string constant() {
        return CONSTANT_NAME;
    }
    public string expr() {
        Expression<Func<methods, string>> ex = e => e.expr();
        return ex.ToString();
    }
    public string exprmember() {
        return expressionName<methods,string>(e => e.exprmember);
    }
    protected string expressionName<T,P>(Expression<Func<T,Func<P>>> action) {
        // https://stackoverflow.com/a/9015598/1037948
        return ((((action.Body as UnaryExpression).Operand as MethodCallExpression).Object as ConstantExpression).Value as MethodInfo).Name;
    }
    public string callermember([CallerMemberName]string name = null) {
        return name;
    }
}

ফলাফল

প্রতিবিম্ব প্রতিবিম্ব

স্ট্যাকট্রেস স্ট্যাকট্রেস

inlineconstant inlineconstant

ধ্রুব ধ্রুবক

expr e => e.expr ()

এক্সপ্রিমবার এক্সপ্রিমবার

callermember প্রধান

Method name retrieval: (reflection) vs (stacktrace) vs (inlineconstant) vs (constant) vs (expr) vs (exprmember) vs (callermember) 

 154673 ticks elapsed ( 15.4673 ms) - reflection
2588601 ticks elapsed (258.8601 ms) - stacktrace
   1985 ticks elapsed (  0.1985 ms) - inlineconstant
   1385 ticks elapsed (  0.1385 ms) - constant
1366706 ticks elapsed (136.6706 ms) - expr
 775160 ticks elapsed ( 77.516  ms) - exprmember
   2073 ticks elapsed (  0.2073 ms) - callermember


>> winner: constant

মনে রাখবেন যে exprএবং callermemberপদ্ধতিগুলি বেশ "সঠিক" নয়। এবং সেখানে আপনি একটি সম্পর্কিত মন্তব্যের পুনরাবৃত্তি দেখতে পাচ্ছেন যে স্ট্যাকট্রেসের চেয়ে প্রতিবিম্ব x 15x দ্রুত।


9

সম্পাদনা: আপনি যে পদ্ধতিতে রয়েছেন (পুরো কলিং স্ট্যাকের বিপরীতে) সম্ভবত মেথডবেজ সম্ভবত করার একটি আরও ভাল উপায়। আমি এখনও ইনলাইনিং সম্পর্কে উদ্বিগ্ন হতে হবে।

আপনি পদ্ধতির মধ্যে স্ট্যাকট্রেস ব্যবহার করতে পারেন:

StackTrace st = new StackTrace(true);

এবং ফ্রেম তাকান:

// The first frame will be the method you want (However, see caution below)
st.GetFrames();

তবে, সচেতন হন যে পদ্ধতিটি যদি অন্তর্ভুক্ত থাকে তবে আপনি যে পদ্ধতিটিকে নিজেরাই ভাবেন সেটির ভিতরে আপনি থাকবেন না। ইনলাইনিং প্রতিরোধ করতে আপনি একটি গুণাবলী ব্যবহার করতে পারেন:

[MethodImpl(MethodImplOptions.NoInlining)]

রিলিজ অপ্টিমাইজেশনের কারণে ইনলাইনটি বিশেষত জটিল কারণ ডিবাগ এবং রিলিজ কনফিগারেশনে কোডটি ভিন্নভাবে আচরণ করবে। ক্ষুদ্র সম্পত্তিগুলির জন্য নজর রাখুন, তারা এর সর্বাধিক ক্ষতিগ্রস্থ।
ডি কে

আমি ভাবছি কেন আপনি এর new StackTrace(true)পরিবর্তে জোরে ব্যবহার করেন new StackTrace(false)। এটি নির্ধারণের trueফলে স্ট্যাকের ট্রেস ফাইলের নাম, লাইন নম্বর এবং ইত্যাদির ক্যাপচারের প্রবণতা সৃষ্টি করবে, যা এই কলটিকে ধীর করে তুলবে। অন্যথায়, একটি দুর্দান্ত উত্তর
Ivaylo স্লাভভ 14

6

ডিল করার সহজ উপায় হ'ল:

System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name;

যদি সিস্টেম.রিফ্লেশনটি ব্যবহারের ব্লকে অন্তর্ভুক্ত থাকে:

MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name;

4

এটি সম্পর্কে কীভাবে:

StackFrame frame = new StackFrame(1);
frame.GetMethod().Name; //Gets the current method name

MethodBase method = frame.GetMethod();
method.DeclaringType.Name //Gets the current class name


0

এটা চেষ্টা কর...

    /// <summary>
    /// Return the full name of method
    /// </summary>
    /// <param name="obj">Class that calls this method (use Report(this))</param>
    /// <returns></returns>
    public string Report(object obj)
    {
        var reflectedType = new StackTrace().GetFrame(1).GetMethod().ReflectedType;
        if (reflectedType == null) return null;

        var i = reflectedType.FullName;
        var ii = new StackTrace().GetFrame(1).GetMethod().Name;

        return string.Concat(i, ".", ii);
    }

0

আমি স্রেফ একটি সাধারণ স্ট্যাটিক ক্লাস দিয়ে এটি করেছি:

using System.Runtime.CompilerServices;
.
.
.
    public static class MyMethodName
        {
            public static string Show([CallerMemberName] string name = "")
            {
                return name;
            }
        }

তারপরে আপনার কোডে:

private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text = MyMethodName.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            textBox1.Text = MyMethodName.Show();
        }

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.