In C++ there are predefined macros such as __FUNCTION__
, which compile to a string literal of the function name the macro is used in.
void MyFunc()
{
printf("I'm in %s!", __FUNCTION__); // I'm in MyFunc!
}
Is there anything similar for C#? I am looking to do this for asp.net web forms:
public string MyProperty
{
get { return (string)ViewState[__PROPERTY__]; }
set { ViewState[__PROPERTY__] = value; }
}
Obviously this doesn't work (otherwise I wouldn't ask the question), I would like to know if there's something similar in C# that doesn't use reflection or have any negative performance impacts versus using a string literal "MyProperty"
.
This will hopefully cut down on typos on my end, but I can think of a few other instances where this would be useful.
Predefined Macros. Unless noted, the macros are defined throughout a translation unit as if they were specified as /D compiler option arguments. When defined, the macros are expanded to the specified values by the preprocessor before compilation. The predefined macros take no arguments and cannot be redefined.
Predefined Macros. The Microsoft C/C++ compiler (MSVC) predefines certain preprocessor macros, depending on the language (C or C++), the compilation target, and the chosen compiler options. MSVC supports the predefined preprocessor macros required by the ANSI/ISO C99 standard and the ISO C++14 and C++17 standards.
The z/OS® XL C/C++ compiler supports these macros as an extension to be compatible with the C99 standard. Except for __FILE__ and __LINE__ , the value of the predefined macros remains constant throughout the translation unit. The predefined macro names typically start and finish with 2 underscore characters.
Next: Undefining and Redefining Macros, Previous: Variadic Macros, Up: Macros [ Contents ] [ Index] Several object-like macros are predefined; you use them without supplying their definitions. They fall into three classes: standard, common, and system-specific.
C#'s preprocessor doesn't support macros with associated values like C++, but what you're trying to do can be done with compilers that support C# 5.0 and greater (so at least VS2012+) through compiler generated Caller Information. Specifically, via the CallerMemberNameAttribute from the System.Runtime.CompilerServices namespace. Based on your question's code, I created the following example to illustrate how you could go about doing what you want to do:
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 to the console. When compiling, the compiler will replace the default value of GetCallerName's memberName argument with the the calling construct's (property, method, etc) name. So there's no code maintenance needed by the programmer
It should also be noted that this has the added benefit of being able to play nice with obfuscation tools, so long as they happen post-compilation.
You could use the 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 returned method name will include the magic get_
or set_
prefixes.
However, I don't think you can really refactor this into an inline macro or function like you could in C++. But if you do refactor a utility method to DRY this out, you could probably just pop the StackTrace back one step to log the caller's information?
I don't know if there is something like a ViewBag
in ASP.NET WebForms. Just in case there isn't, it isn't to difficult to roll you own. You can then wrap the ViewState
in that class and get regular property member access like 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";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With