How to find attribute on method called by lambda expression? - c#

For various reasons, I need to run code that looks like this:
public class MethodRunner {
public T RunMethod<T>(Func<T> method) {
method.Invoke();
}
}
I have a class with a custom attribute that looks like this:
public class MyClass {
[MyAttribute("somevalue")]
public string SayHello(string message) {
Console.WriteLine(message);
return message;
}
}
I can then call MyClass.SayHello by writing
var runner = new MethodRunner();
var myClass = new MyClass();
runner.RunMethod(() => myClass.SayHello("hello!"));
What I would like to do is, in the body of MethodRunner.RunMethod, use reflection to see the parameter of the MyAttribute class on MyClass.SayHello. However, I'm not sure how to get there. All I can see using reflection is the lambda expression itself, not its contents.

It is easy if you are able to change Func<T> into an Expression<Func<T>> instead.
Here is an example if that is possible:
public class MethodRunner {
public T RunMethod<T>(Expression<Func<T>> method) {
var body = method.Body as MethodCallExpression;
if (body == null)
throw new NotSupportedException();
var attributes = body.Method.GetCustomAttributes(false);
// Do something with Attributes
return expression.Compile().Invoke();
}
}
The difficulty when just using Func<T> with () => is that the compiler will generate an actual method. As far as I am aware, you cannot grab "lines" of code out of a method. The one way around this which does not help you since you have parameters is to use RunMethod(myClass.SayHello) instead of RunMethod(() => myClass.SayHello).

Related

Pass property as function argument and convert it name to string inside

I would like to be able to pass any possible type as function parameter.
Now, there is problem with passing property eg.
class Foo
{
public int Bar { get; set; }
}
I'm able to use:
nameof(Foo.Bar)
but I'm unable to do A(Foo.Bar) where in A will be used nameof.
I want to have sure that string is created from property and I would like to have property passed to API and do nameof inside API.
Is there any possibility to pass property through function to nameof? I would like to hide converting of property to string inside of my class instead of getting ready string. How achieve that?
edit: The clue is about:
class B
{
public Prop {get; set;}
}
void foo([?])
{
Console.WriteLine(nameof([?]));
}
What put instead [?] to have console output like: Prop.
The c# compiler uses 'nameof' to kind of find and replace things at compile time, so it won't work how you expect it to. Instead you'll need to get the names of the properties at run-time using either Expressions or Reflection.
Here's an example of how to do it using Expressions:
public static string GetName<T>(Expression<Func<T>> expression)
{
var member = (MemberExpression)expression.Body;
return member.Member.Name;
}
public static string GetName<T>(Expression<Func<T, object>> expression)
{
var body = expression.Body as MemberExpression;
if (body == null)
{
body = ((UnaryExpression)expression.Body).Operand as MemberExpression;
}
return body.Member.Name;
}
public static void PrintName<T>(Expression<Func<T>> expression)
{
Console.WriteLine(GetName(expression));
}
public static void PrintName<T>(Expression<Func<T, object>> expression)
{
Console.WriteLine(GetName(expression));
}
Used like this:
class B
{
public Prop {get; set;}
}
static void Main(string[] args)
{
PrintName<B>((b) => b.Prop);
//Or
var someObject = new B();
PrintName(() => someObject.Prop);
Console.ReadLine();
}
I think you are interpreting nameof a little bit wrong here.
In your first example the method will always print T and does not depend on the type of T. The nameof keyword does nothing other than replacing the expression given to it by a string representation of the expression. e.g. we are giving nameof the parameter T and he will return the string representation of that expression: T.
void A<T>(T smth)
{
Console.Writeline(nameof(T)); // example usage
}
In general the usage of nameof is to provide refactor-able method/property/... names to methods.
For example the ArgumentOutOfRangeException has as parameter the name of the argument that is out of range.
void Test(int value)
{
if (value < 0) throw new ArgumentOutOfRangeException("value");
// yada yada
}
If we provide the name as hardcoded string as in the example above we would get an inconsistency when renaming the parameter.
In order to solve this we use nameof and because we are providing the parameter itself instead of a hardcoded string it is refactor safe.
void Test(int value)
{
if (value < 0) throw new ArgumentOutOfRangeException(nameof(value));
// yada yada
}

Return instance using reflection in C#

A sample code I tried to return an instance of class is given below.
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
How can I mention the class type here since the type is not known at compile time but it will decided at runtime.In the above example i just pass a value 1 (it can be anything and that class will be called accordingly), and the class test1 called.
here I will get an error on the line objcls.callclass(), because objcls is an object instance that doesn't have a callclass()method.
How can I restructure this piece of code? My aim is if I mention a class in the getConstructorclass() method, an object should be returned so as to use it in the further code to invoke the members of that class.
If you know that your classes will have this method, you should use a common interface for them and implement it accordingly. Then you will work with classes that you have made sure it will work.
It would look like this
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
I don't think you should use some generic object returning constructor based on an int variable, if your classes don't have anything in common. It's really weird to handle it like this and it may lead to various problems (some of which you're currently already experiencing). Generic class constructors make sense if the classes are somewhat related and you can predict the outcome, but to create a do-it-all method.. Not so sure about correctness of such approach.
Anyway, if you insist (not recommended, but as you wish), you can create some checks for a type like this:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
But it gets very error prone soon, refactoring will probably be a nightmare etc., but it's your call..
Or you maybe can use solution from pwas, but to me it seems unnecessarily complicated for such a basic task. Looks nice and all, but it still returns only the type "object", so it doesn't really solve your specific problem.
Also, to address one issue I'm not sure you understand - you've already created the instance, you just return type object. That is why you can't call any specific methods on this object, because first you have to cast it to something, that actually has that method and make sure the cast can be done (inheritance etc).
If interface solution (see other answers) is enough, don't look at this answer. When you can't use common base class / interface and you still want call members, you can use solution with is keyword (and check types). Instead of writing many ifs for each case, you can use fluent API:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
Solution:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
Remeber - it would be more elegant to use common interface (as other answers say) - my is only alternative way.
Declare your variable as dynamic
dynamic objcls = getconstrorclass();
Using this the will be determined at run-time, whatever the getconstrorclass method returns. You can access any member of the type and you won't get any error at compile-time. But if you try to access a member which doesn't exists you will get a RuntimeBinderException at runtime.
I would recommend using an interface and restricting the classes that you can instantiate this way to only those that implement the interface.
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
not sure what you want to achieve in the end, but this looks like a job for "Dependency Injection" - here is a nice sample using autofac

Getting parameter name and value from delegate

I have implemented a generic method for calling function in my web service methods and catching exceptions. The idea is to centralize the exception handling and log why the exception occured:
public class WebServiceHandler
{
public T Execute<T>(Func<T> body)
{
//wrap everything in common try/catch
try
{
return body();
}
catch (SoapException)
{
//rethrow any pre-generated SOAP faults
throw;
}
catch (Exception ex)
{
Logger.AddTextToLog(Logger.LogLevel.Error, "An error occured");
var innerExceptionMessage = ex.InnerException != null ? ex.InnerException.Message : "";
throw GenerateSoapException(
ex.Message,
innerExceptionMessage,
SoapException.ServerFaultCode);
}
}
}
I'm using the method like this in my web service methods:
[WebMethod]
GetXXX(string param1, string param2)
{
var request = new GetXXXRequest(param1, param2);
return _webServiceHandler.Execute(() => _controller.GetXXX(request));
}
[WebMethod]
GetYYY(string param1)
{
var request = new GetYYYRequest(param1);
return _webServiceHandler.Execute(() => _controller.GetYYY(request));
}
In case of exceptions I would like to log the parameter names and values used as input to the controller.GetXXX(request) and controller.GetYYY(request) methods in the Execute method.
How can I achieve this?
Or is there a better way to achieve the same goal?
I did not tried with expressions but I have a solution for delegates;
public static List<object> GetMethodParameterValues(Delegate method)
{
var target = method.Target;
if (target == null) return null;
var fields = target.GetType().GetFields();
var valueList = fields.Select(field => field.GetValue(target)).ToList();
return valueList;
}
First of all you can't query the runtime for the that information magically, implicitly.
It is true that you can implicitly learn the complete identity of the currently executing method, its caller, its caller's caller and all of the stacktrace (except for the particular generic arguments in case of generic methods) by instantiating the StackTrace class or by calling the MethodBase.GetCurrentMethod() method.
It is also true that the resulting MethodBase instances hold information about the methods' parameters and so, you might be able to learn the names of the parameters, but that's where it all ends. If a mechanism allowing you to implicitly probe for parameter or local variable values would've been invented then everything would be a lot slower.
What you can do, is help yourself, a bit, by means of the Expression<Lambda> class and its entourage. It's gonna be a bit slow, but you get to choose whether you want reviewable and easy to manage code, or misteriously hard to manage and very very fast code.
Expression<Lambda> is how LINQ manages to not do a full table scan of database tables but rather understand what you did with your query and translate that (at runtime) into SQL or whatever other language you might imagine (depending on the actual LINQ provider).
First of all, I would suggest splitting concerns into 2 categories:
Retrieving names and values (as implicitly as possible)
Using names and values (wherever you want to)
To make that happen you need to think about an entity which can hold the results of point 1. In my suggestion to you that would be a kind of Dictionary<string, object> but you can do whatever suits you best.
My suggestion can be used like so:
public void SomeMethod(string x, int y) {
IDictionary<string, object> paramValues = Helper.TapInto(
() => x,
() => y
);
// paramValues["x"] an paramValues["y"] will hold the values of x and y
}
So, on to the coding bit. You could write a Helper class like so:
public static class Helper {
}
In that Helper class you could invent a static method ( I called mine TapInto maybe that's not the best name for it ) which receives a primitive array of Expression<Func<object>> instances. It does that with a params modifier so that you can easily pass implicit lambdas to it. As a return it gives you a hashtable from string to object representing the "decompiled" variable names and their associated values.
In my case, I also created a private overload of that same method which is actually an "extension" method, to make the code clearer.
public static class Helper {
// ... an overload of the TapInto method is about to appear right here
public static IDictionary<string, object> TapInto(params Expression<Func<object>>[] parameterTouchers) {
var result = new Dictionary<string, object>();
foreach (var toucher in parameterTouchers) {
string name;
object value;
toucher.TapInto(out name, out value);
result[name] = value;
}
return result;
}
So all the public method does is iterate through the list and accumulate the yielded results into the dictionary.
Next let's look at the real magic, which happens in the toucher.TapInto(out name, out value) call:
public static class Helper {
private static void TapInto(this Expression<Func<object>> #this, out string name, out object value) {
Expression expression = #this.Body;
if (expression is UnaryExpression)
expression = (expression as UnaryExpression).Operand;
name = (expression as MemberExpression).Member.Name;
Func<object> compiledLambda = #this.Compile();
value = compiledLambda();
}
// ... public helper method right here
}
What we're doing here is "we're looking inside" the lambda with a magnifying glass.
Because we're gonna use stuff other than object variables it's imminent to observe an implicit conversion like
.. int someParameter ..
object obj = someParameter;
which is only implicit in the actual C# code, but is actually compiled as an explicit conversion:
object obj = (object)someParameter;
But you might have a plain object parameter, like object anotherParam, in which case there would be no conversion at all.
That is why, upon observing the expression's intricate details, I presume I might find a conversion ( represented by the UnaryExpression class ) or not.
Actually it's like saying: In this particular case, my contract to the calling code is that it may send me only stuff which falls into these 2 categories:
Immediate object variable reference: () => someObjectVariable
Variable reference with a conversion: () => (object)x
The contract also accidentally states that the "conversion" bit can be replaced by a UnaryExpression, for instance: () => !someBool.
It also states that you cannot do something like:
() => 123
or () => a + b + c + 100
or anything else in those directions
So, to wrap it up:
You could write your nice little helper
You could use it wherever you want to use it to produce maps between param names and their values although it's not 100% implicit, but at least it won't compile if you rename a parameter without complete refactoring or it will let you rename the parameter references if you choose to rename the parameters using refactoring
(it also works on fields, local variables, etc)
Pass your dictionaries in between parts of your code that are interested in them and use them accordingly !
You can use another parameter to the Execute method to get callback from function.
An Action or your result type. In this case string for example:
public T Execute<T>(Func<T> body, Action<string> callback)
{
//wrap everything in common try/catch
try
{
//do stuff
callback("results are...");
}
You can also use a delegate:
public void CallbackDelegate( string str );
public T Execute<T>(Func<T> body, CallbackDelegate callback)
{
//wrap everything in common try/catch
try
{
//do stuff
callback("results are...");
}
Maybe something like this:
sealed class Param
{
public string Name
{
get;
private set;
}
public object Value
{
get;
private set;
}
public Param(string name, object value)
{
Name = name;
Value = value;
}
}
public T Execute<T>(Func<T> body, params Param[] parameters)
{
//wrap everything in common try/catch
try
{
return body();
}
catch (SoapException)
{
//rethrow any pre-generated SOAP faults
throw;
}
catch (Exception ex)
{
Logger.AddTextToLog(Logger.LogLevel.Error, "An error occured");
foreach (var parameter in parameters)
{
Logger.AddTextToLog(
Logger.LogLevel.Error,
string.Format(
"{0} : {1}",
parameter.Name,
parameter.Value ?? "null"));
}
var innerExceptionMessage = ex.InnerException != null ? ex.InnerException.Message : "";
throw GenerateSoapException(
ex.Message,
innerExceptionMessage,
SoapException.ServerFaultCode);
}
}
And then you call:
[WebMethod]
GetXXX(string param1, string param2)
{
var request = new GetXXXRequest(param1, param2);
return _webServiceHandler.Execute(() => _controller.GetXXX(request)
new Parameter("param1", param1),
new Parameter("param2", param2));
}
What I ended up doing was to add the request class as parameter to the Execute method like this:
public T Execute<T, TU>(Func<T> body, TU parameterClass) where TU : class
{
//wrap everything in common try/catch
try
{
return body();
}
catch (SoapException)
{
//rethrow any pre-generated SOAP faults
throw;
}
catch (Exception ex)
{
var serializedObject = ParameterUtil.GetPropertyNamesAndValues(parameterClass);
Logger.AddTextToLog(Logger.LogLevel.Error, string.Format("An error occured when calling braArkiv Web Services. Web service method arguments: {0}", serializedObject), ex);
var innerExceptionMessage = ex.InnerException != null ? ex.InnerException.Message : "";
throw GenerateSoapException(
ex.Message,
innerExceptionMessage,
SoapException.ServerFaultCode);
}
}
public static class ParameterUtil
{
public static string GetPropertyNamesAndValues<T>(T o) where T : class
{
using (var stringWriter = new StringWriter())
{
var xmlSerializer = new XmlSerializer(o.GetType());
xmlSerializer.Serialize(stringWriter, o);
stringWriter.Close();
return stringWriter.ToString();
}
}
}
Usage:
[WebMethod]
GetXXX(string param1, string param2)
{
var request = new GetXXXRequest(param1, param2);
return _webServiceHandler.Execute(() => _controller.GetXXX(request), request);
}
When an exception occurs I just serialize the parameterClass parameter containing the web service method parameters and add the string to my log.
Thank you all for the constructive input to my question!

Refactor safe way to retrieve a method name

I know a refactor safe way to get the name of a property with this answer. Is there a refactor safe way to get the name of a method?
I am using C# 5 and .Net 4.5.
To illustrate what I'm trying to do:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
//I'd like to get the method names for UnitTestOne and UnitTestTwo here
//in such a way that this code will raise a compile time error if either
//the UnitTestOne or UnitTestTwo method names changes.
}
}
UPDATE: Here is a nice post that explains and provides a flexible utility method to access MethodInfos with refactor safe code. http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
I think Jon Skeet's answer is fine if you only want to cover void parameterless methods. A more general solution would look like this:
public class MyClass
{
public void UnitTestOne(int i) { /* impl */ }
public int UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var methodCallExpressions = new Expression<Action<MyClass>>[] {
mc => mc.UnitTestOne(default(int)), //Note that a dummy argument is provided
mc => mc.UnitTestTwo()
};
var names = methodCallExpressions.Select(mce =>
((MethodCallExpression) mce.Body).Method.Name);
}
}
Note that we use an array of Expression<Action<MyClass>> in order to make a list of method calls on MyClass without knowing the return type and parameter types of each method call. Each method call expression is provided dummy variables to instantiate the expression.
Then the body of each expression is cast to a MethodCallExpression which, as the type name indicates, holds an expression which is just the calling of a method. That type has a Method property which is the MethodInfo of the method being called.
In the link you provided, a property name is extracted similarly using a MemberExpression. Using MethodCallExpression makes the examples quite similar.
By the way, you can also use Expression<Action> instead of Expression<Action<MyClass>> if you prefer. Replace the methodCallExpressions instantiation with:
var methodCallExpressions = new Expression<Action>[] {
() => this.UnitTestOne(default(int)),
() => this.UnitTestTwo()
};
I see this as mostly a stylistic decision, although it would also allow you to encapsulate method calls on a different class, using something like () => (new MyClass2()).UnitTestThree().
The simplest way is probably just to create a delegate for each method, and use the MulticastDelegate.Method property:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var actions = new Action[] { UnitTestOne, UnitTestTwo };
var names = actions.Select(x => x.Method.Name);
}
}

Strong Typing a property name in .NET

Say I have a class with one property
Public Class MyClass
Public Property MyItem() as Object
....
End Property
End Class
I have to pass the name of the property to a function call. (Please don't ask why it should be done this way, its a third party framework). For example
SomeFunc("MyItem")
But what I would like to do is, change the string into a strongly typed parameter. Meaning, if the property name is renamed or changed, it should be reflected here too.
So something of this type :
Dim objectForStrongTyping as New MyClass()
SomeFunc(objectForStrongTyping.MyItem().Name())
I am sure this won't work. Is there a way this strong typing can be done? (C# or VB.NET, any thing is cool)
Here is a solution using classes from System.Linq.Expressions.
static MemberInfo GetMemberInfo<TObject, TProperty>(
Expression<Func<TObject, TProperty>> expression
) {
var member = expression.Body as MemberExpression;
if (member != null) {
return member.Member;
}
throw new ArgumentException("expression");
}
Just throw this in a class somewhere (ExpressionHelper?).
Usage:
class SomeClass {
public string SomeProperty { get; set; }
}
MemberInfo member = GetMemberInfo((SomeClass s) => s.SomeProperty);
Console.WriteLine(member.Name); // prints "SomeProperty" on the console
In C# 6.0 There is a new feature called nameof. Basically you can do this:
var name = nameof(MyClass.MyItem);
Looking at Telerik code converter from C# to VB it seems this is the VB equivalent:
Dim name = nameof([MyClass].MyItem)
So you can do the following:
SomeFunc(nameof(MyClass.MyItem));
Here is the reference to microsoft documentation:
https://learn.microsoft.com/en-us/dotnet/articles/csharp/language-reference/keywords/nameof
This solution works in both C# and VB.NET, but the VB.NET syntax for lambda functions is not as clean, which would probably make this solution less attractive in VB. My examples will be in C#.
You can achieve the effect you want using the lambda function and expression tree features of C# 3. Basically, you would write a wrapper function called SomeFuncHelper and call it like this:
MyClass objForStrongTyping = new MyClass();
SomeFuncHelper(() => objForStrongTyping.MyItem);
SomeFuncHelper is implemented as follows:
void SomeFuncHelper(Expression<Func<object>> expression)
{
string propertyName = /* get name by examining expression */;
SomeFunc(propertyName);
}
The lambda expression () => objForStrongTyping.MyItem gets translated into an Expression object which is passed to SomeFuncHelper. SomeFuncHelper examines the Expression, pulls out the property name, and calls SomeFunc. In my quick test, the following code works for retrieving the property name, assuming SomeFuncHelper is always called as shown above (i.e. () => someObject.SomeProperty):
propertyName = ((MemberExpression) ((UnaryExpression) expression.Body).Operand).Member.Name;
You'll probably want to read up on expression trees and work with the code to make it more robust, but that's the general idea.
Update: This is similar to Jason's solution, but allows the lambda expression inside the helper-function call to be a bit simpler (() => obj.Property instead of (SomeType obj) => obj.Property). Of course, this is only simpler if you already have an instance of the type sitting around.
If there is only one property you could do this - get the property info on the first property of the class:
//C# syntax
typeof(MyClass).GetProperties()[0].Name;
'VB syntax
GetType(MyClass).GetProperties()(0).Name
EDIT Turns out, where you can use expressions, you can also use projection for this kind of reflection (C# code).
public static class ObjectExtensions {
public static string GetVariableName<T>(this T obj) {
System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
if(objGetTypeGetProperties.Length == 1)
return objGetTypeGetProperties[0].Name;
else
throw new ArgumentException("object must contain one property");
}
}
class Program {
static void Main(string[] args) {
Console.WriteLine(Console.WriteLine(new { (new MyClass()).MyItem}.GetVariableName()););
}
}
With this solution, the class can have any number of properties, you would be able to get any other their names.
You could always use a static class that contains string constants instead of passing in a string literal:
public static class ObjectForStrongTyping
{
public const string MyItem = "MyItem";
public const string MyOtherItem = "MyOtherItem";
// ...
}
Your code would then become:
SomeFunc(ObjectForStrongTyping.MyItem);
The best solution I think is to generate static constants using T4 (e.g. T4MVC).
public static class StaticSampleClass
{
public const string MyProperty = "MyProperty";
}
Believe me when you have lots of calls reflection and linq expression is taking down the performance of your application.
Bad thing is T4 is gone in net core. :(
Good thing in C#6.0 u can use nameof(SampleClass.MyProperty)
In the worst case u can use the following example:
using System.Linq.Expressions;
namespace ConsoleApp1
{
public static class Helper
{
public static string GetPropertyName<T>(Expression<Func<T, object>> propertyExpression)
{
var member = propertyExpression.Body as MemberExpression;
if (member != null)
return member.Member.Name;
else
throw new ArgumentNullException("Property name not found.");
}
public static string GetPropertyName<T>(this T obj, Expression<Func<T, object>> propertyExpression)
{
return GetPropertyName(propertyExpression);
}
}
public class SampleClass
{
public string MyProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Property name of type
Console.WriteLine(Helper.GetPropertyName<SampleClass>(x => x.MyProperty));
// Property name of instance
var someObject = new SampleClass();
Console.WriteLine(someObject.GetPropertyName(x => x.MyProperty));
Console.ReadKey();
}
}
}
Performance results (1 million times call):
StaticSampleClass.MyProperty - 8 ms
nameof(SampleClass.MyProperty) - 8 ms
Helper.GetPropertyName<SampleClass>(x => x.MyProperty) - 2000 ms

Categories