Reputation: 1820
Is there a way to get the property's type inside of a getter? Like with reflection or something?
public int Age {
get
{
var myType = {code to get property's type};
//do stuff with myType
}
}
Upvotes: 1
Views: 694
Reputation: 4037
Because I was interested in how this could possibly achieved, I tried to look into the problem.
The first thing we have to note is that properties are syntactic sugar for methods, so we should not care about properties at all.
The second thing is that, if the property is actually a method, its "type" should actually be the return type of the getter. The setters return type is System.Void
, but you only care for getters, so we can ignore that.
So how can we get the return value of the calling method? Like this:
MethodBase.GetCurrentMethod()
Now we get an instance of method base which does not provide a return type, because it represents two types of methods: The regular method and the constructor, which has no return type.
So we can just cast it into a method info and retrieve the return type.
(MethodBase.GetCurrentMethod() as MethodInfo)?.ReturnType
Now we get the current method. But writing that is tedious, is there an easier way to do that? In C++ I'd use a macro for that, but this is not C++, so we have to improvise.
You can get the current StackTrace and retrieve the last calling method like so:
MethodBase method = new StackTrace(1).GetFrame(0).GetMethod();
Passing 1 to the StackTrace
s constructor will give us an offset of 1 (thus skipping the current method off the stack trace), returning the calling method at index 0 when we call GetFrame
. GetMethod
returns a MethodBase
again, so we can just do the following:
(new StackTrace(1).GetFrame(0).GetMethod() as MethodInfo)?.ReturnType;
Using new StackTrace will build the whole stack, but we are only interested in a single frame, so we can just call new StackFrame(1)
to get the last frame. This is a little more performant, because we only care for this frame and can skip the rest. The StackTrace
class builds the whole trace and returns only one frame which is an unnecessary amount of allocation in my opinion.
If you now wrap this up into a static method, you can call it from anywhere and retrieve the current return type.
public static class TypeHelper
{
public static Type GetCallerType() => (new StackFrame(1).GetMethod() as MethodInfo)?.ReturnType;
}
You can now call it in your properties.
public int Property
{
get
{
Console.WriteLine(TypeHelper.GetCallerType());
return 0;
}
}
Calling that will write System.Int32
into the console.
While it was fun to do, I advise against doing it. Getting stuff from reflection at runtime is costly and will take a lot of time.
You still did not state your actual problem, because this feels like an XY Problem to me. But it was a fun thing to tackle. Maybe it helps someone out there.
I used this answer as a reference for the answer provided here, if anyone wants to do more research.
Upvotes: 2
Reputation: 1820
I figured it out. I found the answer to getting the name of the property from another question, which is:
var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4);
And to get the property's type, you use that name and get the property's type from the class that the property is in.
var myType = GetType().GetProperty(propertyName)?.PropertyType
You can use this.GetType()
, but the this
really isn't needed.
Now I can have exactly the same code in ALL of my properties without having to worry about what its name is or what its type is... I can use the same code in a property with ANY name or ANY type. I can pull values from different places (like querystrings) and parse them OUTSIDE of my getters instead of writing parsing code in EVERY getter in xxx number of properties.
Upvotes: -1