I got this class
public class fooBase { public List<MethodsWithCustAttribute> MethodsList; public bool fooMethod([CallerMemberName]string membername ="")) { //This returns a value depending of type and method } public void GetMethods() { // Here populate MethodsList using reflection } }
And This Attribue Class
// This attribute get from a database some things, then fooMethod check this attribute members public class CustomAttribute { public string fullMethodPath; public bool someThing ; public bool CustomAttribute([CallerMemberName]string membername ="") { fullMethodPath = **DerivedType** + membername // I need here to get the type of membername parent. // Here I want to get CustClass, not fooBase } }
Then I have this
public class CustClass : fooBase { [CustomAttribute()] public string method1() { if (fooMethod()) { .... } } }
I need the Type name of the CallerMember, there is something like [CallerMemberName] to get the Type of class owner of the Caller ?
You can use StackFrame of System. Diagnostics and MethodBase of System. Reflection . StackFrame(Int32, Boolean) initializes a new instance of the StackFrame class that corresponds to a frame above the current stack frame, optionally capturing source information.
[CallerMemberName] applies the caller's member name. [CallerFilePath] applies the path to the caller's source code file. [CallerLineNumber] applies the line number in the caller's source code file.
It isn't foolproof, but the convention with .NET is to have one type per file and to name the file the same as the type. Our tooling also tends to enforces this convention i.e. Resharper & Visual Studio.
Therefore it should be reasonable to infer the type name from the file path.
public class MyClass { public void MyMethod([CallerFilePath]string callerFilePath = null, [CallerMemberName]string callerMemberName = null) { var callerTypeName = Path.GetFileNameWithoutExtension(callerFilePath); Console.WriteLine(callerTypeName); Console.WriteLine(callerMemberName); } }
Granted, getting the caller member name is not "natural" in the object model. That's why the C# engineers introduced CallerMemberName in the compiler.
The real enemy is duplication, and stack-based workarounds are inefficient.
[CallerMemberName]
allows to get the information without duplication and without ill-effect.
But getting the caller member type is natural and easy to get without duplication.
Add a "caller" parameter to fooMethod
, no special attribute needed.
public bool fooMethod(object caller, [CallerMemberName]string membername = "") { Type callerType = caller.GetType(); //This returns a value depending of type and method return true; }
And call it like this:
fooMethod(this);
You stated
// Here I want to get CustClass, not fooBase
and that's exactly what you'll get.
While this exactly answers your requirements, there are other, different, cases where it wouldn't work.
In those cases, a [CallerMemberType]
might make sense, but there are simpler solutions. Notice that the static caller case is simpler: there is no object so no discrepancy between it and the type of the calling method. No fooBase
, only CustClass
.
If at least one caller is a static method, then don't do the GetType()
inside the method but on call site, so don't pass "this" to the method but the type:
public bool fooMethodForStaticCaller(Type callerType, [CallerMemberName]string membername = "")
Static caller will do:
public class MyClassWithAStaticMethod // can be CustClass, too { public static string method1static() { fooMethodForStaticCaller(typeof(MyClassWithAStaticMethod)); } }
To keep compatibility with object callers, either keep the other fooMethod
that takes the this
pointer, or you can remove it and object callers will do:
fooMethod(this.GetType());
You can notice that the typeof(MyClassWithAStaticMethod)
above repeats the class name and it's true. It would be nicer to not repeat the class name, but it's not such a big deal because this repeats only once, as a typed item (not a string) and inside the same class. It's not as serious a problem as the original problem that the [CallerMemberName]
solves, which was a problem of repeating the caller name in all call sites.
For example, in class fooBase
you want to call anotherFooMethod
from object context but want the type being passed to always be fooBase
, not the actual type of the object (e.g. CustClass
).
In this case there is a this
pointer but you don't want to use it. So, just use actually the same solution:
public class fooBase { [CustomAttribute()] public string method1() { if (anotherFooMethod(typeof(fooBase))) { .... } } }
Just like in case 1, there is one repetition, not one per call site, unless you have an pre-existing problem of rampant code duplication, in which case the problem being addressed here is not the one you should worry about.
[CallerMemberType]
might still make sense to avoid duplication at all, but:
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