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
Related
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
}
I am writing a small validation fluent API for validating commands which I am using in the following way:
Validator.Candidate(foo).Verify(x => x.Name).IsNotNull();
Effectively, the verify method passes the value of the lambda expression (in this case a string extracted from the foo.Name property) to a set of extension methods, for example IsNotNull(), IsGreaterThan(10) etc. The extension methods can then raise errors if needed and so on.
The underlying classes and extension methods used in the API are:
public static class Validator
{
public static ValidationCandidate<T> Candidate<T>(T candidate)
{
return new ValidationCandidate<T>(candidate);
}
}
public class ValidationCandidate<T> : IValidatorCandidate<T>
{
public ValidationCandidate(T candidate)
{
Object = candidate;
}
public T Object { get; private set; }
}
public class ValidatorProperty<TCommand, TProperty> : IValidatorProperty
{
public static ValidatorProperty<TCommand, TProperty> Verify<TCommand, TProperty>(this IValidatorCandidate<TCommand> candidate, Expression<Func<TCommand>> func)
{
return new ValidatorProperty<TCommand, TProperty>(candidate, func.Invoke(candidate.Object), name);
}
}
public class ValidatorProperty<TCommand, TProperty> : IValidatorProperty
{
public ValidatorProperty(IValidatorCandidate<TCommand> candidate, TProperty value, string name) {
}
public TProperty Value { get; private set; }
public IValidatorCandidate<TCommand> Candidate { get; private set; }
}
The IsNotNull() extension show above is not important and unrelated to the problem at hand.
The problem is that in the Verify() method I am passing a lambda to select a property of the object used in Candidate().
What I want to be able to do is restrict the lambda used in Verify() to only allow properties of the candidate object to be passed in, i.e. if the candidate object is defined as:
public Foo() {
string Name { get; set; }
}
I want to be able to do:
Validator.Object(instanceOfFoo).Verify(x => x.Name).....
but NOT:
Validator.Object(instanceOfFoo).Verify(x => "Hello")....
At the moment both usages above will compile. I think this is because I have written the signature for the lamda in Verify incorrectly for what I want to do and don't know how to write it to do what I want it to!
The lambda needs to be written in such as what that if an attempt is made to pass something into Verify that is not a property of Foo (or whatever object is being used as the candidate object) then a compiler error is thrown. I don't want to do the check at runtime.
There's no way to express that constraint in C#, and therefore there is no way for the compiler to check it at compile time.
However, you can catch it before runtime by using static code analysis. The easiest way for you to do that is probably to use Roslyn: https://msdn.microsoft.com/en-us/magazine/dn879356.aspx
This way, you can give immediate feedback to the developer, and catch any errors at buildtime.
This question already has answers here:
get name of a variable or parameter [duplicate]
(3 answers)
Closed 2 years ago.
I would like to be able to retrieve the name of a property of a type using a strongly typed syntax.
I already got a function to get a property name of an instance:
public static string PropertyName<T, TReturn>(this T obj, Expression<Func<T, TReturn>> property) where T : class
{
MemberExpression body = (MemberExpression) property.Body;
if (body == null) throw new ArgumentException("The provided expression did not point to a property.");
return body.Member.Name;
}
Which can be called like this:
Car car = new Car();
car.PropertyName(x => x.Wheels) //returns "Wheels"
I'm trying to create another function that could support the following:
Type t = Typeof(Car);
t.PropertyName(x => x.Wheels) //should return "Wheels"
Or just (even better!):
Car.PropertyName(x => x.Wheels)
How would I go about this?
You can rewrite your method to use it without creating an instance:
var prop = ReflectionHelper.PropertyName<Car>(x => x.Wheels);
because your don't use obj inside because you don't need it:
public static class ReflectionHelper
{
public static string PropertyName<T>(Expression<Func<T, object>> property) where T : class
{
MemberExpression body = (MemberExpression)property.Body;
return body.Member.Name;
}
}
Note that the return type doesn't have to be strongly-typed, it can be just object.
In C# 6 and higher, the syntactical goodness of using static can make usages of this sort of method much more readable. It will also give you early binding / compile-time checks, so CodeLens will show you usages to your property that used to be referenced as string literals (like in lots of data binding code floating around out there). This makes refactoring much easier when you have to rename properties down the road.
The code here builds on #abatishchev's answer, because in this scenario (where you don't have an instance of the type in question), using extension methods makes the code more verbose, not less.
There’s also an additional line in the PropertyName method to handle the point by #pedro-faustino about exceptions casting UnaryExpression. (That wouldn’t be needed if the method had a second type parameter in the propertyExpression argument, for the return type, e.g. Expression<Func<T, TMember>>).
That said, here’s an example of how you could wire up data bindings in an early-bound manner with this kind of strategy:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using BusinessObjects.Vehicles;
using static MyCoolHelperMethods;
namespace Helpers
{
public static class MyCoolHelperMethods
{
public static string PropertyName<T>(Expression<Func<T, object>> propertyExpression) where T : class
{
var memberExpression = propertyExpression.Body as MemberExpression
?? (propertyExpression.Body as UnaryExpression)?.Operand as MemberExpression;
return memberExpression?.Member.Name;
}
}
}
namespace Application
{
using System.Windows.Forms;
public class Car
{
public string Make {get; set;}
public string Model {get; set;}
}
// imagine this is a form with textboxes for car Make and Model:
public partial class MyWindowsForm
{
public MyWindowsForm()
{
var car = new Car();
this.txtCarMake.DataBindings.Add(new Binding(
propertyName: PropertyName<TextBox>(x => x.Text),
dataSource: car,
dataMember: PropertyName<Car>(x => x.Make),
// formattingEnabled is needed to avoid invalid cast
// exceptions assigning the object property to the control:
formattingEnabled: true));
this.txtCarModel.DataBindings.Add(new Binding(
propertyName: PropertyName<TextBox>(x => x.Text),
dataSource: car,
dataMember: PropertyName<Car>(x => x.Model),
// formattingEnabled is needed to avoid invalid cast
// exceptions assigning the object property to the control:
formattingEnabled: true));
}
}
}
#abatishchev example only works if Wheels is a reference type.
If you have the following
public class Car
{
public int ID;
}
And you try to call this
var prop = ReflectionHelper.PropertyName<Car>(x => x.ID);
You'll get the following exception
InvalidCastException: Unable to cast object of type
'System.Linq.Expressions.UnaryExpression' to type
'System.Linq.Expressions.MemberExpression'.
I think this has to do with the fact that you are passing a value type to the expression, so it has to be boxed into an object. If you pass a reference type, it doesn't need to be boxed to object.
What you can do instead is this:
var prop = ReflectionHelper.PropertyName((Car x) => x.ID);
public static class ReflectionHelper
{
public static string PropertyName<T, P>(Expression<Func<T, P>> property)
where T : class
{
MemberExpression body = (MemberExpression)property.Body;
return body.Member.Name;
}
}
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).
Various parts of the .NET framework require the use of the string name of a property:
ArgumentException uses the name of the offending variable
DependencyProperty uses the name of the property it backs
INotifyPropertyChanged uses the name of the property which just changed.
The easiest approach to populate these parameters seems to be hard coding them (ie: new ArgumentNullException("myArg")). This seems excessively fragile it's not until runtime that you'll realize your refactoring broke the association.
Using reflection to validate these parameters is the only solution that jumps out to me but said validation is till only performed at run-time.
Is there a better way of defining the relationship between a member and it's name? Preference will be given to a simple but elegant design-time enforcement.
You can use an Expression statement to link the name.
throw new SomeException<MyType>(x => x.myArg)
Where the expression follows Expression<Func<TSource, TValue>>. Then, refactorings and what not actually change the expression. Your exception then parses the expression and pulls the name from the property.
You can just write your reflection code to do the validation, and then run it in a post-build step. That way the validation step becomes part of the compilation process and is reported pretty much like a compile error.
(However, beware of a bug in Visual Studio due to which it is still possible to run a failed build by simply pressing “Run” a second time without making any changes...)
How are you planning to do the validation? If you want to use just the .NET’s built-in reflection capabilities, you will have to examine the method IL as raw bytes. This ILReader class will help you turn those bytes into something meaningful that you can analyse.
You can use an Expression<Func<T, object>> to do this as follows:
using System;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication3
{
public class MyClass
{
public int IntegralValue { get; set; }
public void Validate()
{
if (this.IntegralValue < 0)
throw new ArgumentOutOfRangeException(PropertyHelper.GetName<MyClass>(o => o.IntegralValue));
}
}
public static class PropertyHelper
{
/// <summary>Extracts the property (member) name from the provided expression.</summary>
public static string GetName<T>(this Expression<Func<T, object>> expression)
{
MemberExpression memberExpression = null;
if (expression.Body is MemberExpression)
memberExpression = (MemberExpression)expression.Body;
else if (expression.Body is UnaryExpression)
memberExpression = (((UnaryExpression)expression.Body).Operand as MemberExpression);
if (memberExpression == null)
throw new ApplicationException("Could not determine member name from expression.");
return memberExpression.Member.Name;
}
}
public static class Program
{
public static void Main(string[] args)
{
MyClass good = new MyClass() { IntegralValue = 100 };
MyClass bad = new MyClass() { IntegralValue = -100 };
try { good.Validate(); }
catch (Exception ex)
{
Console.WriteLine(ex);
}
try { bad.Validate(); }
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
}
Output
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: IntegralValue
at ConsoleApplication3.MyClass.Validate() in d:\...\ConsoleApplication3\Program.cs:line 14
at ConsoleApplication3.Program.Main(String[] args) in d:\...\ConsoleApplication3\Program.cs:line 50
Explanation
This will allow you to use a lambda to reference property names. The GetName method inspects the provided expression and extracts the name of the member that you've specified. This way, when you rename a property and refactor the change, all of these lambdas are automatically updated. No more strings needed!
I used to use PostSharp (an "AOP" framework for .net) to put scattered pieces in one place (arg and its name), for example:
void MyMethod([NotNull] object arg1) {}
would automatically generate MSIL code (at compile time) to do the validation and throw the exception.
It addresses your example, it probably can made be work for other related scenarios.