Get Attribute from Function<T> - c#

How I can get a custom attribute from a Function object?
public static void Main(string[] args) {
Func<object> fun = () => Foo();
//fun. Get Foo Custom Attribute
}
[CustomAttrib]
public static object Foo() {
return new object();
}

With a Function, the information you're looking for is not available AFAIK.
However, if it were an Expression, it would be quite easy:
Expression<Func<object>> expression = () => Foo();
var method = ((MethodCallExpression)expression.Body).Method;
Console.WriteLine(method.GetCustomAttributes(false)[0]);
You can convert an Expression to a Function with the Compile() method.
var fun = expression.Compile();
This might be helpful if you define the Function yourself, but not if comes from some 3rd party code which you can't modify.

Related

C# member method as static method ("reversed extension method")

Is it possible in C# to get a reference to a member function without specifying the object, so that it is usable like a static extension method, taking the object as first parameter?
class Handler
{
public void Add(int value) { ... }
}
static class HandlerExtensions
{
public static void AddEx(this Handler instance, int value) { ... }
}
var x = new Handler();
// possible:
Action<int> func1 = x.Add;
Action<Handler, int> func2 = HandlerExtensions.AddEx;
// not possible?
Action<Handler, int> func3 = Handler::Add;
Why would I want to do that? To specify methods to call in a class before having an actual object to work with:
// current solution:
void RegisterDto<DataType>(Func<Handler, Action<DataType>> handler) { ... }
RegisterDto<int>(x => x.Add);
// desired solution:
void RegisterDto<DataType>(Action<Handler, DataType> handler) { ... }
RegisterDto<int>(Handler::Add); // <--- does syntax for this exist?
If you mean "can you create a delegate like that" then the answer is "yes, but it's slightly ugly". I don't think you can use a method group conversion, but you can use reflection and Delegate.CreateDelegate, e.g.
MethodInfo method = typeof(Handler).GetMethod("Add");
var action = (Action<Handler, int>)
Delegate.CreateDelegate(typeof(Action<Handler, int>), method);
It would be nice to have a method group conversion here, I agree.
This might not work for you use-case, but you can create a delegate with
Action<Handler, int> f = (h, v) => h.Add(v);
And to use it
var handler = new Handler();
f(handler, 100);
If you don't want to evaluate it each time, maybe you could make it Lazy
Func<Lazy<Handler>, Action<int>> addMethod = target => target.Value.Add;
// example of usage
var lazyHandler = new Lazy<Handler>();
Test(addMethod(lazyHandler), 1);

Pass method name from property to lambda without arguments

I am trying to achieve the following:
this.helper.Verify(i => i.SomeModule.SomeMethod);
Where:
i is a known type.
SomeModule is a public property of this type.
SomeMethod is the name of the method (passed as delegate I assume).
I would like to be able to avoid specifying the generic types in the Verify method.
Thats how far I've been able to go:
public void Verify<TProp, TResult>(
Expression<Func<KnownType, TProp>> moduleExpression,
Expression<Func<TProp, TResult>> methodExpression)
{
var moduleIdentifier = (moduleExpression.Body as MemberExpression).Member.Name;
var methodIdentifier = (methodExpression.Body as MethodCallExpression).Method.Name;
this.Verify(moduleIdentifier, methodIdentifier, state);
}
But this forces me to write the argument values for the methodExpression, like:
this.helper.Verify(
i => i.SomeModule,
m => m.SomeMethod(arg1, arg2));
Is there a way to achieve what I am looking for?
Finally I end up with a solution that requires delegates.
I need to analyze an expression that can have multiple arguments, like:
i => i.Car.Engine.Intake.Open()
I will extract the last two arguments as a "module" and "method":
public class ExpressionTools
{
public string GetLastInstanceName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (MemberExpression)methodCallExpression.Arguments.Reverse().Skip(1).First();
var instanceName = methodInfoExpression.Member.Name;
return instanceName;
}
public string GetMethodName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
return methodInfo.Name;
}
}
Solution with delegates
A class with generics can be reused since the delegates are not necessary to analyze the expression:
public class Verifier
{
public void Verify<TDelegate>(Expression<Func<KnownType, TDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var moduleName = tools.GetLastInstanceName(methodExpression);
var methodName = tools.GetMethodName(methodExpression);
// My logic.
}
}
Now I need to create the delegates, For that I created a file and declared them without a class:
namespace Whatever
{
public delegate void VoidDelegate();
public delegate void VoidBoolDelegate(bool value);
// etc...
}
Finally, I need to maintain a class that has the same method overloaded with the different delegates.
public class FakeExtensions
{
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidBoolDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
}
Alternative solution without delegates
The easiest solution would be to pass a default value for each parameter, but that would express that the values are also verified, which is not the case. I really dislike the idea of having something like this:
this.helper.Verify(i => i.SomeModule.SomeMethod(0, false, 0.0, null);
Since Moq is part of our testing framework, it is possible to use It.IsAny as a value for each parameter of a method call, wich expresses that the values don't matter:
this.helper.Verify(i => i.SomeModule.SomeMethod(It.IsAny<int>, It.IsAny<bool>, It.IsAny<double>, It.IsAny<SomeType>);
Why did I choose the delegates solution
I have to verify some calls on a low-level 3rd party API that has methods with up to 100 parameters. I think that the burden of maintaining a delegates list and method overloads pays off in maintainability, readability and ease of use.

Get the name of a method using an expression

I know there are a few answers on the site on this and i apologize if this is in any way duplicate, but all of the ones I found does not do what I am trying to do.
I am trying to specify method info so I can get the name in a type safe way by not using strings.
So I am trying to extract it with an expression.
Say I want to get the name of a method in this interface:
public interface IMyInteface
{
void DoSomething(string param1, string param2);
}
Currently I can get the name using THIS method:
MemberInfo GetMethodInfo<T>(Expression<Action<T>> expression)
{
return ((MethodCallExpression)expression.Body).Method;
}
I can call the helper method as follows:
var methodInfo = GetMethodInfo<IMyInteface>(x => x.DoSomething(null, null));
Console.WriteLine(methodInfo.Name);
But I am looking for the version that I can get the method name without specifying the parameters (null, null)
like this:
var methodInfo = GetMethodInfo<IMyInteface>(x => x.DoSomething);
But all attempts fail to compile
Is there a way to do this?
x => x.DoSomething
In order to make this compilable I see only two ways:
Go non-generic way and specify it's parameter as Action<string, string>
Specify Action<string, string> as your target delegate type by yourself: GetMethodInfo<IMyInteface>(x => new Action<string,string>(x.DoSomething))
if you are ok to go with second one, which allows you to omit arguments then you can write your GetMethodInfo method as follows:
MemberInfo GetMethodInfo<T>(Expression<Func<T, Delegate>> expression)
{
var unaryExpression = (UnaryExpression) expression.Body;
var methodCallExpression = (MethodCallExpression) unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression) methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo) methodInfoExpression.Value;
return methodInfo;
}
It works for your interface, but probably some generalization will be required to make this working with any method, that's up to you.
The following is compatible with .NET 4.5:
public static string MethodName(LambdaExpression expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodCallObject = (ConstantExpression)methodCallExpression.Object;
var methodInfo = (MethodInfo)methodCallObject.Value;
return methodInfo.Name;
}
You can use it with expressions like x => x.DoSomething, however it would require some wrapping into generic methods for different types of methods.
Here is a backwards-compatible version:
private static bool IsNET45 = Type.GetType("System.Reflection.ReflectionContext", false) != null;
public static string MethodName(LambdaExpression expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
if (IsNET45)
{
var methodCallObject = (ConstantExpression)methodCallExpression.Object;
var methodInfo = (MethodInfo)methodCallObject.Value;
return methodInfo.Name;
}
else
{
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
return methodInfo.Name;
}
}
Check this sample code on Ideone.
Note, that Ideone does not have .NET 4.5.
The problem with this is that x.DoSomething represents a method group. And you have to somehow explicitly specify what delegate type do you want to convert that method group into, so that the correct member of the group can be selected. And it doesn't matter if that group contains only one member.
The compiler could infer that you mean that one, but it doesn't do that. (I think it's this way so that your code won't break if you add another overload of that method.)
Snowbear's answer contains good advice on possible solutions.
This is a new answer to an old question, but responds to the "verbose" complaint of the accepted answer. It requires more code, but the result is a syntax like:
MemberInfo info = GetActionInfo<IMyInterface, string, string>(x => x.DoSomething);
or, for methods with a return value
MemberInfo info = GetFuncInfo<IMyInterface, object, string, string>(x => x.DoSomethingWithReturn);
where
object DoSomethingWithReturn(string param1, string param2);
Just like the framework provides Action<> and Func<> delegates up to 16 parameters, you have to have GetActionInfo and GetFuncInfo methods that accept up to 16 parameters (or more, although I'd think refactoring is wise if you have methods with 16 parameters). A lot more code, but an improvement in the syntax.
If you are ok with using the nameof() operator you can use the following approach.
One of the benefits is not having to unwrap an expression tree or supply default values or worry about having a non-null instance of the type with the method.
// As extension method
public static string GetMethodName<T>(this T instance, Func<T, string> nameofMethod) where T : class
{
return nameofMethod(instance);
}
// As static method
public static string GetMethodName<T>(Func<T, string> nameofMethod) where T : class
{
return nameofMethod(default);
}
Usage:
public class Car
{
public void Drive() { }
}
var car = new Car();
string methodName1 = car.GetMethodName(c => nameof(c.Drive));
var nullCar = new Car();
string methodName2 = nullCar.GetMethodName(c => nameof(c.Drive));
string methodName3 = GetMethodName<Car>(c => nameof(c.Drive));
If your application would allow a dependency on Moq (or a similar library), you could do something like this:
class Program
{
static void Main(string[] args)
{
var methodName = GetMethodName<IMyInteface>(x => new Action<string,string>(x.DoSomething));
Console.WriteLine(methodName);
}
static string GetMethodName<T>(Func<T, Delegate> func) where T : class
{
// http://code.google.com/p/moq/
var moq = new Mock<T>();
var del = func.Invoke(moq.Object);
return del.Method.Name;
}
}
public interface IMyInteface
{
void DoSomething(string param1, string param2);
}

How do I take a lambda expression as a parameter that returns a method?

I want to be able to do this:
var test = SomeMethod(s => s.SomeMethod);
I can make it work with properties by making the method signature look like this:
SomeMethod<TProperty>(Expression<Func<T, TProperty>> expression)
How can I make it work with methods? I know this is simple, I'm just missing something small.
Moq approaches this by requiring the method parameters to be stubbed out with special 'marker' objects like:
test.Setup(m => m.SomeMethod(It.IsAny<int>()));
Incidentally, this allows Moq to resolve method overloads (a single method name is ambiguous if you don't have any notion of the required parameters.) They are going a bit further and using it to actually match parameters based on criteria, for the purpose of mocking objects for unit testing. The source code is available and might give you some ideas. They do all sorts of fun trickery with expression trees.
Here is an example based on the Moq source (hacked out a bit, but shows how the method can be extracted from the expression):
internal static void ExtractMethod<T>(Expression<Action<T>> expression)
where T : class
{
var methodCall = expression.ToMethodCall();
var method = methodCall.Method;
var args = methodCall.Arguments.ToArray();
}
Straight from Moq source:
/// <summary>
/// Casts the body of the lambda expression to a <see cref="MethodCallExpression"/>.
/// </summary>
/// <exception cref="ArgumentException">If the body is not a method call.</exception>
public static MethodCallExpression ToMethodCall(this LambdaExpression expression)
{
Guard.NotNull(() => expression, expression);
var methodCall = expression.Body as MethodCallExpression;
if (methodCall == null)
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
Resources.SetupNotMethod,
expression.ToStringFixed()));
}
return methodCall;
}
This will work with your code, but you'd have to pass 'dummy' parameters to allow the compiler to create the expression. So if you had:
public void SomeMethod(int value, string text) {}
Then you'd pass it as:
ExtractMethod(s => s.SomeMethod(0, null));
Is something like this what you're looking for?
DoSomethingWithAction<T>(Func<T, Action> actionRetriever) { }
DoSomethingWithFunction<T, TResult>(Func<T, Func<TResult>> functionRetriever) { }
You would call these like:
DoSomethingWithAction<ObjectWithMethod>(obj => obj.Method);
DoSomethingWithFunction<ObjectWithProperty>(obj => obj.Property);
Something like this?
public SimpleCommand( Predicate<object> canExecuteDelegate, Action<object> executeDelegate )
{
CanExecuteDelegate = canExecuteDelegate;
ExecuteDelegate = executeDelegate;
}
You will need to specify the function signature using Predicate or Action.
class Program
{
public class Test
{
public bool SomeMethod(string test)
{
return true;
}
}
static void Main(string[] args)
{
Test testObj = new Test();
Func<string, bool> rule1 = AddRule(testObj, x => x.SomeMethod);
bool rsult = rule1("ttt");
}
static Func<string, bool> AddRule<T>( T obj, Func<T,Func<string, bool>> func)
{
return func(obj);
}
}
I think, there's no way of doing this without specifying the method signature: Just think of overloaded methods:
void SomeMethod() { }
int SomeMethod(int a, int b) { return 0; }
// ...
var test = TestMethod(s => s.SomeMethod);
How would the compiler possibly know, which of the methods you want to test?

Expression tree - how to get at declaring instance?

I'm a newbie when it comes to expression trees, so I'm not sure how to ask this question or what terminology to use. Here's an overly-simplifed version of what I'm trying to do:
Bar bar = new Bar();
Zap(() => bar.Foo);
public static void Zap<T>(Expression<Func<T>> source)
{
// HELP HERE:
// I want to get the bar instance and call bar.Zim() or some other method.
}
How can I get to bar inside the Zap method?
Since the expression passed into your Zap method is a tree, you just need to walk the tree using an Expression Tree Visitor and look for the first ConstantExpression in the expression. It will likely be in the following sequence:
(((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value
Note that the bar instance is captured by a closure, which is implemented as an internal class with the instance as a member, which is where the 2nd MemberExpression comes from.
EDIT
Then you have to get the field from the generated closure like so:
static void Main(string[] args)
{
var bar = new Bar();
bar.Foo = "Hello, Zap";
Zap(() => bar.Foo);
}
private class Bar
{
public String Foo { get; set; }
}
public static void Zap<T>(Expression<Func<T>> source)
{
var param = (((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value;
var type = param.GetType();
// Note that the C# compiler creates the field of the closure class
// with the name of local variable that was captured in Main()
var field = type.GetField("bar");
var bar = field.GetValue(param) as Bar;
Debug.Assert(bar != null);
Console.WriteLine(bar.Foo);
}
If you know the type of "bar", you can do this (I'm reusing some bits from the codekaizen's answer here):
static void Main(string[] args)
{
var bar = new Bar();
bar.Foo = "Hello, Zap";
Zap(() => bar.Foo);
Console.ReadLine();
}
private class Bar
{
public String Foo { get; set; }
}
public static void Zap<T>(Expression<Func<T>> source)
{
var body = source.Body as MemberExpression;
Bar test = Expression.Lambda<Func<Bar>>(body.Expression).Compile()();
Console.WriteLine(test.Foo);
}
In most cases, you can find an expression representing your object within an expression tree, and then compile and execute this expression and get the object (but this is not a very fast operation, by the way). So, the bit you were missing is the Compile() method. You can find a little bit more info here: How to: Execute Expression Trees.
In this code, I assume that you always pass an expression like "() => object.Member". For a real-world scenario you will need either to analyze that you have an expression you need (e.g. just throw an exception if it's not a MemberExpression). Or use ExpressionVisitor, which is kind of tricky.
I have recently answered a very similar question here:
How do I subscribe to an event of an object inside an expression tree?
Standing on the shoulders of giants above, my final extension method to extract the instance of the class that represented the source of the expression looks as follows:
public static TIn GetSource<TIn, TOut>(this Expression<Func<TIn, TOut>> property)
where TIn: class
{
MemberExpression memberExpression = (MemberExpression)property.Body;
TIn instance = Expression.Lambda<Func<TIn>>(memberExpression.Expression).Compile()();
return instance;
}
I built on all of the answers above, thanks to all.

Categories