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
}
Related
I have a static method that is used for checking the argument...
require(myStringVariable);
If the value does not meet some requirements, I just want do display a message.
Is it possible to display also the name of the variable (or the expression) passed as the argument? (In C++, a macro with stringize operator would do the job. Is there any equivalent or other tool to do the same in C#?)
Update: I am not searching anything like nameof(myStringVariable). Actually, I would like to call the method also like:
require(bareFname + ".ext");
and if the expression would not pass the check, then I would to do inside the method something like
static void required(... theExpressionArgument)
{
string value = evaluate theExpressionArgument;
if (value.Length == 0)
{
Console.WriteLine("ERROR: Non empty value is required for the expression "
+ theExpressionArgument);
}
}
Based on this answer, you could rewrite your method like this:
public static void RequireNotEmpty(Expression<Func<string>> lambda)
{
// Get the passed strings value:
string value = lambda.Compile().Invoke();
// Run the check(s) on the value here:
if (value.Length == 0)
{
// Get the name of the passed string:
string parameterName = ((MemberExpression) lambda.Body).Member.Name;
Console.WriteLine($"ERROR: Non empty value is required for the expression '{parameterName}'.");
}
}
which can then be called like this:
string emptyString = "";
RequireNotEmpty(() => emptyString);
and writes
ERROR: Non empty value is required for the expression 'emptyString'.
Note that above code assumes that you only want to check for strings. If that's not the case, you could use the signature public static void RequireNotEmpty<T>(Expression<Func<T>> lambda) which will then work for any type T.
Also I renamed the method to something I find both more readable and more meaningful.
EDIT: Recommendation
After reading your comments, I figured this might be what you want:
public static class Checker
{
private static T GetValue<T>(Expression<Func<T>> lambda)
{
return lambda.Compile().Invoke();
}
private static string GetParameterName<T>(Expression<Func<T>> lambda)
{
return ((MemberExpression) lambda.Body).Member.Name;
}
private static void OnViolation(string message)
{
// Throw an exception, write to a log or the console etc...
Console.WriteLine(message);
}
// Here come the "check"'s and "require"'s as specified in the guideline documents, e.g.
public static void RequireNotEmpty(Expression<Func<string>> lambda)
{
if(GetValue(lambda).Length == 0)
{
OnViolation($"Non empty value is required for '{GetParameterName(lambda)}'.");
}
}
public static void RequireNotNull<T>(Expression<Func<T>> lambda) where T : class
{
if(GetValue(lambda) == null)
{
OnViolation($"Non null value is required for '{GetParameterName(lambda)}'.");
}
}
...
}
And now you can utilise the Checker class like this:
public string DoStuff(Foo fooObj, string bar)
{
Checker.RequireNotNull(() => fooObj);
Checker.RequireNotEmpty(() => bar);
// Now that you checked the preconditions, continue with the actual logic.
...
}
Now, when you call DoStuff with an invalid parameter, e.g.
DoStuff(new Foo(), "");
the message
Non empty value is required for 'bar'.
is written to the console.
I would like to create a function allow to get data from any classes with provide a key value, but I am stack when converting object back to the class. The following is my code.
var ListABC = new List<ABC>();
GetData(ListABC, typeof(ABC), "A1");
Here is my Function :-
Public void GetData(object obj, Type objType, string find)
{
// Note! not able to using (List<ABC>)obj, because you never know what tyoe of object will be pass in.
// How to get list data of "A1" after List ABC as a object? assume this function allow any classes.
}
Here is my class :-
public class ABC {
protected int _A1;
protected bool _B1;
protected string _C1;
public int A1
{
get
{
return this._A1;
}
set
{
this._A1 = value;
}
}
public bool B1
{
get
{
return this._B1;
}
set
{
this._B1 = value;
}
}
public string C1
{
get
{
return this._C1;
}
set
{
this._C1 = value;
}
}
}
As Daniel said, make GetData generic:
public void GetData<T>(IList<T> obj, string find)
{
}
and then call it like so:
GetData(ListABC, "A1");
You can even enforce constraints on T, for example:
public void GetData<T>(IList<T> obj, string find)
where T: IConvertible
{
}
If you don't want to implement an interface on the list item objects you will pass here, you could also pass a func:
public void GetData<T>(IList<T> obj, Func<T, string> idFunc, string find)
{
var matchingItems = obj.Where(o => idFunc(o) == find);
}
and call it like so:
GetData(ListABC, i => i.A1, "A1");
Edit: Do you just want ListABC.Select(i => i.A1) ?
If you want minimum change in your code. you can do it like below.
Although, making method generic is good idea, but as you are already passing type of ABC to the method, you are not required to make method generic.
here type you have passed is suggesting which type of data list is holding
Assumptions: you method's return type is void (so assuming you don't want anything to be returned. and also you are passing only one string find as a property to get so at a time you want data of only specified property.
if your requirements are simpler and scope of data is limited in your method only, you can always choose simpler way (which is easily understandable and readable)
try something like below,
public void GetData(object obj, Type objType, string find)
{
//as you are passing type of list here, you can use it.
if(objType == typeof(ABC))
{
List<ABC> list = (List<ABC>)obj;
//now use it.
//here we are getting the property with name as per find (name we passed in method)
PropertyInfo prop = objType.GetProperty(find);
//if there is no property with specified name, PropertyInfo object (prop) will be null
if (prop != null)
{
if (prop.PropertyType == typeof(int))
{
foreach (ABC abcObj in list)
{
object a1Data = prop.GetValue(abcObj);
int data = (int)a1Data;
}
}
}
}
}
Note: drawback of this approach is, you need to handle cases of different Types in this method. So if your method may accept big variety of type, you may not want to go with this idea.
I want to write a method that will analyze custom attributes of any method (with any number of arguments and any return type) knowing only method info.
This function will check if method has specific Attribute. like this: var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false); and if it has such attribute It will execute it.And I want to make call of that function really easy to use. So, in example there are three methods and method GetMethodAttributes that I want to call.
class Test
{
public static void Main()
{
}
public void Test1(){}
public void Test2(int a){}
public void Test3(object a, string c, Boolean d);
public void GetMethodAttributes(MethodInfo mi) {}
}
Ideally I want to write something like that
public static void Main()
{
var t = new Test();
GetMethodAttributes(t.Test1);
GetMethodAttributes(t.Test2);
GetMethodAttributes(t.Test3);
}
I don't want to use string representation of the method names as method names may change, like that:
MethodInfo info = type.GetMethod(name);
Do I have any options? Basically I need a way to use delegates for functions with different sinatures
As Chris Sinclair pointed out in the comment above; you can use a delegate without using reflection or expression trees to get the MethodInfo. The downside is that the compiler is not able to infer the generic parameter so you have to specify the delegate type to match the signature of the given method like this:
public class Test
{
public static void Main()
{
var t = new Test();
CheckMethodAttributes<Action>(t.Test1);
CheckMethodAttributes<Action<int>>(t.Test2);
CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
}
public void Test1() { }
public void Test2(int a) { }
public void Test3(object a, string c, bool d) { }
public static void CheckMethodAttributes<T>(T func)
{
MethodInfo method = new MethodOf<T>(func);
// Example attribute check:
var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
if (ignoreAttribute != null)
{
// Do something here...
}
}
}
This uses two utility classes, the MethodOf<T> for extracting the MethodInfo from the given Delegate and some AttributeUtils to get strongly typed custom attribute retrieval:
public static class AttributeUtils
{
public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.IsDefined(typeof(TAttribute), inherit);
}
public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
}
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
}
}
public class MethodOf<T>
{
public MethodOf(T func)
{
var del = func as Delegate;
if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");
Method = del.Method;
}
private MethodInfo Method { get; set; }
public static implicit operator MethodOf<T>(T func)
{
return new MethodOf<T>(func);
}
public static implicit operator MethodInfo(MethodOf<T> methodOf)
{
return methodOf.Method;
}
}
You can do something like this using Expression Trees, where you pass the method via a lambda expression. You do still need to pass stub values for the parameters, however. For a good example of this in action, check out the source code for Moq, which uses this pattern extensively for setting up mock behaviors for unit testing. Just note that this is not a trivial thing to set up. If you need something relatively quick and dirty, your best bet is probably string names with a good refactoring tool and/or automated tests to help deal with the renaming issues.
I need to get the type of a property that will only be known at run time and pass this as a type parameter for a generic method. For example:
PropertyInfo prop = Bar.GetProperty("Property1");
//"type 'prop' could not be found" error
Foo<prop.PropertyType>();
void Foo<T>()
{
//Stuff
}
class Bar
{
string Property1{get;set;}
}
The type of Bar.Property1 will not be known at compile time, so I can't do Foo<string>();. It will compile and run correctly if I use Foo<dynamic>(); but I'm not convinced that's the best way to go, and I'd like to know if there is a way to do it using an older framework.
Hopefully, this more complete example will make my intentions clearer:
public void Map(TInType inObject, TOutType outObject)
{
//propertyIn, propertyOut, and converter are all strings identifying the properties/methods to be used from the inObject/Type outObject/Type.
SetPropertyValues<dynamic, dynamic>(inObject, outObject, propertyIn, propertyOut, converter);
}
private void SetPropertyValues<TPropIn,TPropOut>(TInType fromObject, TOutType toObject, string propertyIn, string propertyOut, string converter)
{
PropertyInfo prop1 = typeof(TInType).GetProperty(propertyIn);
MethodInfo converterMethod = typeof(TInType).GetMethod(converter);
PropertyInfo prop2 = typeof(TOutType).GetProperty(propertyOut);
prop2.SetValue(
toObject,
CopyPropertyValue<TPropIn, TPropOut>((TPropIn)prop1.GetValue(fromObject, null), p => (TPropOut)converterMethod.Invoke(fromObject, new object[] { p })),
null);
}
private TPropOut CopyPropertyValue<TPropIn, TPropOut>(TPropIn InPropValue, Func<TPropIn, TPropOut> converterFunction)
{
return converterFunction(InPropValue);
}
I'm open to any other suggestions anyone may have, or that the code should be taken out back and shot, but my original question is still the one I'm most interested in.
You can use MakeGenericMethod, performance is actually quite reasonable and allows you to explicitly define what you are calling with what, so reduces the overhead.
So something like the following, the Invoker would call the explicit method / class you need, and the helper actually invokes the generic call.
public class GenericHelper
{
public static void DoSomethingGeneric(GenericInvokerParameters parameters)
{
var targetMethodInfo = typeof(GenericInvoker).GetMethod("DoSomethingGeneric");
var genericTargetCall = targetMethodInfo.MakeGenericMethod(parameters.InvokeType);
genericTargetCall.Invoke(new GenericInvoker(), new[] { parameters });
}
}
public class GenericInvoker
{
public void DoSomethingGeneric<T>(GenericInvokerParameters parameters)
{
//Call your generic class / method e.g.
SomeClass.SomeGenericMethod<T>(parameters.SomeValue);
}
}
public class GenericInvokerParameters
{
public GenericInvokerParameters(Type typeToInvoke, string someValue)
{
SomeValue = someValue;
InvokeType = typeToInvoke;
}
public string SomeValue { get; private set; }
public Type InvokeType { get; private set; }
}
Don't see anything bad in dynamic.
Use it.
EDIT
Till you're not going to call that method with high frequency, where the reflection could bit it from performance perspective, I would prefer dynamic
Foo should not be generic if you are not using it generically. Just make it operate on type Object instead of T.
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