Predefined Macros for Method Names

In C ++, there are predefined macros, such as __FUNCTION__ , which are compiled into a string literal of the name of the function in which the macro is used.

 void MyFunc() { printf("I'm in %s!", __FUNCTION__); // I'm in MyFunc! } 

Is there something similar for C #? I want to do this for asp.net web forms:

 public string MyProperty { get { return (string)ViewState[__PROPERTY__]; } set { ViewState[__PROPERTY__] = value; } } 

Obviously this will not work (otherwise I would not ask a question), I would like to know if there is something similar in C # that does not use reflection or does not have negative performance impacts compared to using a string literal "MyProperty" .

This will hopefully reduce typos at my end, but I can come up with a few other examples where this would be useful.

+4
source share
3 answers

You can use StackTrace and StackFrame to get the name of the current method.

 StackTrace st = new StackTrace(); StackFrame sf = st.GetFrame(1); string method = sf.GetMethod().ToString(); 

For properties, the name of the returned method will include the magic get_ or set_ .

However, I don’t think you can really reorganize this into an inline macro or function, like in C ++. But if you refactor the DRY utility method, could you just click StackTrace one step to register the caller information?

+3
source

The C # preprocessor does not support macros with related values, such as C ++, but what you are trying to do can be done using compilers that support C # 5.0 and above (at least VS2012 +) using the compiler generated Caller Information . In particular, through CallerMemberNameAttribute from the System.Runtime.CompilerServices namespace. Based on your interrogation code, I created the following example to illustrate how you can do what you want:

 using System; class ViewState { public string this[string propertyName] { get { return propertyName; } set { } } }; class View { ViewState mState = new ViewState(); static string GetCallerName( [System.Runtime.CompilerServices.CallerMemberName] string memberName = "") { return memberName; } public string MyProperty { get { return (string)mState[GetCallerName()]; } set { mState[GetCallerName()] = value; } } }; class Program { static void Main(string[] args) { var view = new View(); Console.WriteLine(view.MyProperty); Console.ReadKey(); } }; 

"MyProperty" will be printed on the console. At compilation, the compiler will replace the default value for the memberCName GetCallerName argument with the name of the calling construct (property, method, etc.). Therefore, the programmer does not require code maintenance

It should also be noted that this has the added benefit that you can play well with obfuscation tools if they happen after compilation.

+5
source

I don't know if there is something like ViewBag in ASP.NET WebForms. Just in case, it’s not difficult for you to roll. You can then wrap the ViewState in this class and get regular access to resource membership as you wish.

 public class ExpandoViewState : DynamicObject { private readonly StateBag _viewState; public ExpandoViewState(StateBag viewState) { _viewState = viewState; } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = _viewState[binder.Name]; if (result != null) return true; return base.TryGetMember(binder, out result); } public override bool TrySetMember(SetMemberBinder binder, object value) { _viewState[binder.Name] = value; return true; } } ... dynamic state = new ExpandoViewState(ViewState); var val = (string)state.MyProperty; state.MyProperty = "hi"; 
+1
source

Source: https://habr.com/ru/post/1443247/


All Articles