This question already has answers here:
Get property name and type using lambda expression
(4 answers)
Closed 9 years ago.
This is a cursory question I can't quite answer.
The main program
class Program{
static void Main(string[] args){
Console.WriteLine("Begin");
var myClass = new MyClass();
Util.Print(myClass.Id);
Util.Print(myClass.Server);
Util.Print(myClass.Ping);
Console.WriteLine("End");
}
}
How do I implement the Util.Print method to get this output to the console:
Begin
Id
Server
Ping
End
Assuming you don't want to use strings, the most common answer is via an Expression - essentially emulating the missing infoof; you would have to use something like:
Console.WriteLine("Begin");
var myClass = new MyClass();
Util.Print(() => myClass.Id);
Util.Print(() => myClass.Server);
Util.Print(() => myClass.Ping);
Console.WriteLine("End");
Assuming they are all properties/fields (edit added method-call support):
public static class Util
{
public static void Print<T>(Expression<Func<T>> expr)
{
WriteExpression(expr);
}
public static void Print(Expression<Action> expr) // for "void" methods
{
WriteExpression(expr);
}
private static void WriteExpression(Expression expr)
{
LambdaExpression lambda = (LambdaExpression)expr;
switch (lambda.Body.NodeType)
{
case ExpressionType.MemberAccess:
Console.WriteLine(((MemberExpression)lambda.Body)
.Member.Name);
break;
case ExpressionType.Call:
Console.WriteLine(((MethodCallExpression)lambda.Body)
.Method.Name);
break;
default:
throw new NotSupportedException();
}
}
}
In addition to Marc's answer: here is an article which explains several ways to do what you want to do (one such method uses expressions).
public string Id {
get {
return "Id;"
}
}
Hehe erm, though I assume that's not what you mean :-( The answer will likely be something to do with reflection.
Take a look at http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx
Related
This question already has answers here:
Calling a function from a string in C#
(5 answers)
Closed 4 years ago.
I'm using WPF mvvm pattern anyway if some method got string parameter is this possible calling like
SomeClass1 sc = new SomeClass();
DummyClass2 dc = new DummyClass2();
public void SomeMethod(string param) //param = "SomeMethodName"
{
sc.'param'(dc);
}
The key is calling class object's fuction via param without branch or Data structure mapping.
maybe using reflection.. any good idea?
Yes that's possible via reflection. You can use the Invoke method.
It would look something like this:
MethodInfo method = type.GetMethod(name);
object result = method.Invoke(objectToCallTheMethodOn);
Having said that, in normal circumstances you shouldn't use reflection to call methods in c#. It's only for really special cases.
Here's a full example:
class A
{
public int MyMethod(string name) {
Console.WriteLine( $"Hi {name}!" );
return 7;
}
}
public static void Main()
{
var a = new A();
var ret = CallByName(a, "MyMethod", new object[] { "Taekyung Lee" } );
Console.WriteLine(ret);
}
private static object CallByName(A a, string name, object[] paramsToPass )
{
//Search public methods
MethodInfo method = a.GetType().GetMethod(name);
if( method == null )
{
throw new Exception($"Method {name} not found on type {a.GetType()}, is the method public?");
}
object result = method.Invoke(a, paramsToPass);
return result;
}
This prints:
Hi Taekyung Lee!
7
This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 5 years ago.
I have some ugly code that looks something like this:
switch (f.TypeName)
{
case "TypeOne":
ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod<TypeOne>), args);
break;
case "TypeTwo":
ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod<TypeTwo>), args);
break;
...
case "TypeTwenty":
ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod<TypeTwenty>), args);
break;
}
I would really like to get rid of the switch statement and do something along these lines:
var myTypeDescriptor = Type.GetType(f.TypeName); //<== clearly not this, but similar
ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod<myTypeDescriptor>), args);
where MyMethod looks like this:
protected void MyMethod<T>(object args)
{
...
}
I've poked around some and have found a number of examples where the generic is a generic class, but no examples where it is a generic method. And definitely not any examples where it is being passed to a delegate.
While this appears, at first glance, to be a duplicate of How do I use reflection to call a generic method?, I am not simply trying to call the method. It is being passed to the WaitCallback delegate. Perhaps this is a two part question: 1) how do I retrieve the generic method via reflection and 2) having obtained a handle to the method, how do I pass it as an argument to the WaitCallback delegate?
Anyone have any ideas? Is this even possible?
Here is brief idea
var type = Type.GetType(f.TypeName);
var methodInfo = typeof(MethodHoderType).GetMethod("MyMethod");
var constructedMethodInfo = methodInfo.MakeGenericMethod(type);
constructedMethodInfo.Invoke(...);
If it is instance method you should create an instance of type type to pass to Invoke method or pass null as first parameter if it is static method.
Look at the Type.GetType Method (String) and MethodInfo.MakeGenericMethod Method (Type[]) for more information.
If you can create instances of the types from the strings you have (if you know them fully qualified), you can use MethodInfo.MakeGenericMethod(Type[] typeArguments)
Take a look at the docs in MSDN.
Hope this Helps. Instead of a string Just build a decorator to take in the Type that Queues the Item.
class Program
{
static void Main(string[] args)
{
var arguments = new object();
Execute<ObjectA>(args);
Execute<ObjectB>(args);
Execute<ObjectC>(args);
Execute<ObjectA>(args);
Console.ReadLine();
}
static void Execute<T>(object args) where T:BaseObject
{
ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod<T>), args);
}
static void MyMethod<T>(object args) where T:BaseObject
{
Console.WriteLine(typeof(T).FullName);
}
}
public class BaseObject
{
}
public class ObjectA : BaseObject
{
}
public class ObjectB : BaseObject
{
}
public class ObjectC : BaseObject
{
}
This question already has answers here:
Compiler Ambiguous invocation error - anonymous method and method group with Func<> or Action
(4 answers)
Closed 7 years ago.
In my application, I have code similar to following:
class Program
{
static void Main(string[] args)
{
Method(uri => Task.FromResult(uri));
}
static void Method(Func<Uri, Uri> transformer)
{
throw new NotImplementedException();
}
static void Method(Func<Uri, Task<Uri>> transformer)
{
throw new NotImplementedException();
}
}
As expected, running this code calls the second overload of 'Method', the one expecting a function delegate that returns a task. However, if i change the code to avoid using the anonymous method in Main:
class Program
{
static void Main(string[] args)
{
Method(Method2);
}
static Task<Uri> Method2(Uri uri)
{
return Task.FromResult(uri);
}
static void Method(Func<Uri, Uri> transformer)
{
throw new NotImplementedException();
}
static void Method(Func<Uri, Task<Uri>> transformer)
{
throw new NotImplementedException();
}
}
The C# compiler now complains that my call to 'Method' is ambiguous. What am i missing?
The long answer is at https://stackoverflow.com/a/2058854/1223597 (as richzilla pointed out).
The short answer is that the C# compiler team chose to make method group conversions (like Method(Method2)) ignore the return type (here of Method2). This gives them flexibility in how Expression trees are parsed. Unfortunately that means the compiler cannot implicitly choose between your 2 Method signatures.
When doing a lambda conversion, (Method(uri => Task.FromResult(uri))), the compiler team doesn't need to worry about expression tree parsing, so they do consider return types.
As you can see in the code below, I have declared an Action<> object as a variable.
Would anybody please let me know why this action method delegate behaves like a static method?
Why does it return true in the following code?
Code:
public static void Main(string[] args)
{
Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };
Console.WriteLine(actionMethod.Method.IsStatic);
Console.Read();
}
Output:
This is most likely because there are no closures, for example:
int age = 25;
Action<string> withClosure = s => Console.WriteLine("My name is {0} and I am {1} years old", s, age);
Action<string> withoutClosure = s => Console.WriteLine("My name is {0}", s);
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
This will output false for withClosure and true for withoutClosure.
When you use a lambda expression, the compiler creates a little class to contain your method, this would compile to something like the following (the actual implementation most likely varies slightly):
private class <Main>b__0
{
public int age;
public void withClosure(string s)
{
Console.WriteLine("My name is {0} and I am {1} years old", s, age)
}
}
private static class <Main>b__1
{
public static void withoutClosure(string s)
{
Console.WriteLine("My name is {0}", s)
}
}
public static void Main()
{
var b__0 = new <Main>b__0();
b__0.age = 25;
Action<string> withClosure = b__0.withClosure;
Action<string> withoutClosure = <Main>b__1.withoutClosure;
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
}
You can see the resulting Action<string> instances actually point to methods on these generated classes.
The "action method" is static only as a side effect of the implementation. This is a case of an anonymous method with no captured variables. Since there are no captured variables, the method has no additional lifetime requirements beyond those for local variables in general. If it did reference other local variables, its lifetime extends to the lifetime of those other variables (see sec. L.1.7, Local variables, and sec. N.15.5.1, Captured outer variables, in the C# 5.0 specification).
Note that the C# specification only talks about anonymous methods being converted to "expression trees", not "anonymous classes". While the expression tree could be represented as additional C# classes, for example, in the Microsoft compiler, this implementation is not required (as acknowledged by sec. M.5.3 in the C# 5.0 specification). Therefore, it is undefined whether the anonymous function is static or not. Moreover, section K.6 leaves much open as to the details of expression trees.
Delegate caching behavior was changed in Roslyn. Previously, as stated, any lambda expression which didn't capture variables was compiled into a static method at the call site. Roslyn changed this behavior. Now, any lambda, which captures variables or not, is transformed into a display class:
Given this example:
public class C
{
public void M()
{
var x = 5;
Action<int> action = y => Console.WriteLine(y);
}
}
Native compiler output:
public class C
{
[CompilerGenerated]
private static Action<int> CS$<>9__CachedAnonymousMethodDelegate1;
public void M()
{
if (C.CS$<>9__CachedAnonymousMethodDelegate1 == null)
{
C.CS$<>9__CachedAnonymousMethodDelegate1 = new Action<int>(C.<M>b__0);
}
Action<int> arg_1D_0 = C.CS$<>9__CachedAnonymousMethodDelegate1;
}
[CompilerGenerated]
private static void <M>b__0(int y)
{
Console.WriteLine(y);
}
}
Roslyn:
public class C
{
[CompilerGenerated]
private sealed class <>c__DisplayClass0
{
public static readonly C.<>c__DisplayClass0 CS$<>9__inst;
public static Action<int> CS$<>9__CachedAnonymousMethodDelegate2;
static <>c__DisplayClass0()
{
// Note: this type is marked as 'beforefieldinit'.
C.<>c__DisplayClass0.CS$<>9__inst = new C.<>c__DisplayClass0();
}
internal void <M>b__1(int y)
{
Console.WriteLine(y);
}
}
public void M()
{
Action<int> arg_22_0;
if (arg_22_0 = C.
<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 == null)
{
C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 =
new Action<int>(C.<>c__DisplayClass0.CS$<>9__inst.<M>b__1);
}
}
}
Delegate caching behavior changes in Roslyn talks about why this change was made.
As of C# 6, this will always default to instance methods now, and will never be static (so actionMethod.Method.IsStatic will always be false).
See here: Why has a lambda with no capture changed from a static in C# 5 to an instance method in C# 6?
and here: Difference in CSC and Roslyn compiler's static lambda expression evaluation?
The method has no closures and also references a static method itself (Console.WriteLine), so I would expect it to be static. The method will declare an enclosing anonymous type for a closure, but in this instance it is not required.
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