basically I want to do this:
Func<string> f = ()=> MyMethodName();
only having a string name of a method, i.e.:
Func<string> f = "MyMethodName";
Can this be done? Any problems, caveats? Can Reflection help? Can I first check if a method exist?
You don't need a lambda expression at all here. You can use Delegate.CreateDelegate:
MethodInfo method = GetType().GetMethod(methodName);
Func<string> func = (Func<string>) Delegate.CreateDelegate(typeof(Func<string>),
obj, method);
That way you avoid a level of indirection, and you also do the reflection part once instead of on every invocation.
Here is an example with reflection:
Func<string> func = ( ) => {
return ( string )( this.GetType( ).GetMethod( "MyMethodName" ).Invoke( this, new object[ 0 ] ) );
}
If you want something to ease this thing here is something:
public static Func<string> ReflectByName( object obj, string methodname ) {
return ( ) => {
return ( string )( obj.GetType( ).GetMethod( methodname ).Invoke( obj, new object[ 0 ] ) );
}
}
How to use:
Func<string> f = FastReflect.ReflectByName( this, "MyMethodName" );
FastReflect where is the method ReflectByName is in.
Here is another way to do it. This has the advantage of being massively faster than reflection so is great if you need to call it in a loop. This code creates a Func that will call your method
public static Func<T, string> CreateCallFunc<T>(string methodName)
{
var parm = Expression.Parameter(typeof(T));
var call = Expression.Call(parm, typeof(T).GetMethod(methodName));
var lambda = Expression.Lambda<Func<T, string>>(call, parm);
return (Func<T, string>)lambda.Compile();
}
you use it like this:
class SomeClass
{
void DoIt()
{
var func = CreateCallFunc<SomeClass>("SomeMethod");
Console.WriteLine(func(this));
}
public string SomeMethod()
{
return "it works!";
}
}
The big advantage is that once you have created your Func, you can call it very simply just using func(myInstance) and it will be very fast.
I use this method for taking a DataReader and copying all the data from the reading into a collection of classes where the property names on the class match the fields in the reader.
Note that John's answer is a much easier way to do this, which I wasn't aware of until now, but this has greater flexibility I guess
Related
I have a dictionary that contains a string as a key, and a function to run when said string has been discovered. It then passes in the object used that was discovered. I merely want access to this object within the function body, but am unsure how to do it. I presume the lambda operator has to be used, but i don't really know how to properly use it.
public Dictionary<string, Func<object, bool>> stringReceivedRegister;
My setup
string received_name = StringFormater.GetName(receivedMessage);
object changed_string = openMethod.Invoke(instance, new object[] { receivedMessage });
StringTypes.Instance.stringReceivedRegister[received_name].Invoke(changed_string);
When adding a function to the stringReceivedRegister how would i access it within the function i pass in?
StringTypes.Instance.stringReceivedRegister.Add("Test", function where i can get access to 'changed string');
To add a function to stringReceivedRegister, your first need to declare a method:
private static bool MyFunction(object x) {
// ...
}
And then you can pass MyFunction to Add:
// Note the absence of () after "MyFunction". I am not actually calling it
stringReceivedRegister.Add("Test", MyFunction);
The x parameter will refer to changed_string when you do this:
StringTypes.Instance.stringReceivedRegister[received_name].Invoke(changed_string);
It's quite annoying to have to declare a method very time, so C# 3 provided lambda expressions, allowing you to do this:
stringReceivedRegister.Add("Test", x => {
// ...
});
Again, x will refer to changed_string when you invoke the delegate with changed_string.
Look at this code:
static bool FunctionTest(object o) {
return true;
}
static void Main(string[] args) {
Dictionary<string, Func<object, bool>> dict = new Dictonary<string, Func<object, bool>>();
dict.Add("A", ((obj) => { return false; }));
dict.Add("B", FunctionTest);
Console.WriteLine(dict["A"](1));
Console.WriteLine(dict["B"](1));
I have found following part of code in some examples while learning Func<> syntax:
public static class Lambda
{
public static int MyFunc(Func<string, int> func)
{
//some logic
return 0;
}
}
And sample call :
var getInt = Lambda.MyFunc((url) => { Console.WriteLine(url); return 0; }
And My Question :
Why passing above func as lambda expression with this (url) is allowed if value is never assigned ( or maybe is ?)?
What is the point of passing Func like this ?
Edit :
To clarify my question . I was only wondering about this sample call - why passing string as argument like above (using lambda (url) => {} ) is not forbidden by compiler if the value can not be initiated. Is there any example that can be useful with passing string like above ?
url is the name of the parameter for the lambda expression. It's like writing a method like this:
public static int Foo(string url)
{
Console.WriteLine(url);
return 0;
}
Then creating a delegate from it:
Func<string, int> func = Foo;
Now in order to call the delegate, you need to provide it a string - and that then becomes the value of the parameter, just like if you called the method normally:
int result = func("some url");
I have an example class
public class MyClass{
ActionResult Method1(){
....
}
[Authorize]
ActionResult Method2(){
....
}
[Authorize]
ActionResult Method3(int value){
....
}
}
Now what I want is to write a function returning true/false that can be executed like this
var controller = new MyClass();
Assert.IsFalse(MethodHasAuthorizeAttribute(controller.Method1));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method2));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method3));
I got to the point where
public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function)
{
return function.Method.GetCustomAttributes(typeof(AuthorizeAttribute), false).Length > 0;
}
would work for Method3. Now how can I do that generic in a way that it'll take strings and classes as parameters as well?
The issue with your code is the signature of public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function). MethodHasAuthorizeAttribute can only be used with arguments matching the signature of the delegate you specified. In this case a method returning an ActionResult with a parameter of type int.
When you call this method like MethodHasAuthorizeAttribute(controller.Method3), the Compiler will do a method group conversion. This might not always be desired and can yield unexpected results (Method group conversions aren't always straigthforward). If you try to call MethodHasAuthorizeAttribute(controller.Method1) you will get a compiler error because there's no conversion.
A more general solution can be constructed with expression trees and the famous "MethodOf" trick. It employs compiler generated expression trees to find the invocation target:
public static MethodInfo MethodOf( Expression<System.Action> expression )
{
MethodCallExpression body = (MethodCallExpression)expression.Body;
return body.Method;
}
You can use it like this, but it can also be used with any method:
MethodInfo method = MethodOf( () => controller.Method3( default( int ) ) );
With that out of the way, we can build a general implementation:
public static bool MethodHasAuthorizeAttribute( Expression<System.Action> expression )
{
var method = MethodOf( expression );
const bool includeInherited = false;
return method.GetCustomAttributes( typeof( AuthorizeAttribute ), includeInherited ).Any();
}
Okay, thats for methods. Now, if you want to apply the Attribute check on classes or fields to (I'll spare properties because they are actually methods), we need to perform our check on MemberInfo, which is the inheritance root for Type, FieldInfo and MethodInfo. This as easy as extracting the Attribute search into a separate method and providing appropriate adapter methods with nice names:
public static bool MethodHasAuthorizeAttribute( Expression<System.Action> expression )
{
MemberInfo member = MethodOf( expression );
return MemberHasAuthorizeAttribute( member );
}
public static bool TypeHasAuthorizeAttribute( Type t)
{
return MemberHasAuthorizeAttribute( t );
}
private static bool MemberHasAuthorizeAttribute( MemberInfo member )
{
const bool includeInherited = false;
return member.GetCustomAttributes( typeof( AuthorizeAttribute ), includeInherited ).Any();
}
I'll leave the implementation for fields as an exercise, you can employ the same trick as MethodOf.
There is a easier solution availabe compared to the others above with the current .NET/C# version (4.6.1, C#6):
If you only have one one method with that name:
var method = typeof(TestClass).GetMethods()
.SingleOrDefault(x => x.Name == nameof(TestClass.TestMethod));
var attribute = method?.GetCustomAttributes(typeof(MethodAttribute), true)
.Single() as MethodAttribute;
Now to check if you have the attribute set on the method:
bool isDefined = attribute != null;
And if you want to access the properties of the attribute, you can do this easy as that:
var someInfo = attribute.SomeMethodInfo
If there are multiple methods with the same name, you can go on and use method.GetParameters() and check for the parameters, instead of .GetMethods().Single...
If you know that your method has no parameters, this check is easy:
var method = typeof(TestClass).GetMethods()
.SingleOrDefault(
x => x.Name == nameof(TestClass.TestMethod)
&& x.GetParameters().Length == 0
);
If not, this is going to be more complicated (checking parameters, etc.) and the other solutions are way easier and robust to use.
So: Use this if you have no overloads for a method, or only want to read attributes from a method with a specified amount of parameters.
Else, use the MethodOf provided by other answers in here.
I do something like that:
public static bool MethodHasAuthorizeAttribute(this Delegate pMethod, string pRoleAccess)
{
var mi = pMethod.GetMethodInfo();
const bool includeInherited = false;
var atr = mi.GetCustomAttributes(typeof(AuthorizeAttribute), includeInherited)
.Select(t => (AuthorizeAttribute)t)
.Where(t => pRoleAccess.Length>0?t.Roles == pRoleAccess:true);
if (pRoleAccess == String.Empty)
{
return !atr.Any();
}
else
{
return atr.Any();
}
}
public static bool MethodHasAllowAnonymousAttribute(this Delegate pMethod)
{
var mi = pMethod.GetMethodInfo();
const bool includeInherited = false;
var atr = mi.GetCustomAttributes(typeof(AllowAnonymousAttribute), includeInherited);
return atr.Any();
}
Calling it follows
Func<string,System.Web.Mvc.ActionResult> func = controller.Login;
bool atrAuthorize = func.MethodHasAuthorizeAttribute(String.Empty);
If you make use of FluentAssertions you can do the following:
var classInstance = new MyClass();
Func<ActionResult> method1 = classInstance.Method1;
method1.GetMethodInfo().Should().BeDecoratedWith<AuthorizeAttribute>();
Func<ActionResult> method2 = classInstance.Method2;
method2.GetMethodInfo().Should().BeDecoratedWith<AuthorizeAttribute>();
Func<int, ActionResult> method3 = classInstance.Method3;
method3.GetMethodInfo().Should().BeDecoratedWith<AuthorizeAttribute>();
Find some sample where i find the methods in a class that have a specified attribute applied.
private static void GetMethodInfo(object className)
{
var methods = className.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach(var m in methods)
{
var parameters = m.GetParameters();
var att = m.GetCustomAttributes(typeof (CustomAttribute), true);
}
}
The parameter that is passed is an instance of a class. You can modify the code to suit your requirement which should be pretty easy.
Lets say i have the following code
private Func<T> _method;
public void SetExecutableMethod<T>(Func<T> methodParam)
{
_method = methodParam;
}
public T ExecuteMethod(object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
ParameterInfo[] methodParams = method.GetParameters();
//So i now have a list of parameters for the method call,
//How can i update the parameter values for each of these?
for (int i = 0; i < parameters.Count(); i++ )
{
methodParams[i] = ???''
}
return _method.Compile()();
}
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod(new object[]{"Test1", "Test2"});
T result2 = ExecuteMethod(new object[]{"Test3", "Test4"}););
}
In the above code, i want to set a private variable to some Func that points to an anonymoust function and never have to set it again.
I then would like to be able to call ExecuteMethod(...) with different parameters. This method should update the parameter values of the variable _method and then invoke the method.
I can read the number of parameters and their values fine, i just am not sure how to set the values for those parameter? Any thoughts on this?
This is not the way to do it. Right now, your _method field is a delegate of type Func<T>, and you expect that its body contains yet another method which is actually executed. That is a lot to expect from your callers. I would forget about this approach and look for something different.
One way would be to supply a method which takes an array of objects as its parameter (Func<object[], T>), and then invoke it directly with appropriate parameters (but never a method in its body). Even this is less common for a strongly typed language like C# since you lose all type safety (but then again, you do want to be pretty flexible with this framework you are designing).
The other way would be to get a MethodInfo instance, and then use its Invoke method. In a way, this might even express your intents better, because it will be obvious that the executable method is capable of virtually anything.
Next, you could use generics to get some type safety, and require that all your input parameters are wrapped inside a single parameter class. In that case, you might have a strongly typed Func<Tparam, Tresult> method, and your Execute method would accept a Tparam instance as its parameter. This would void the need for any reflection.
[Edit]
As I wrote, I would try to avoid reflection. Since you wrote you basically need a cache of method results, a simple approach might be something like:
Create a wrapper for your list of parameters so that you can compare them "by value". I added an example class, but you might even want to allow passing an IEqualityComparer explicitly, so that you don't have to override Equals for each partial parameter.
// implements `IEquatable` for a list of parameters
class Parameters : IEquatable<Parameters>
{
private readonly object[] _parameters;
public Parameters(object[] parms)
{
_parameters = parms;
}
#region IEquatable<Parameters> Members
public bool Equals(Parameters other)
{
if (other == null)
return false;
if (_parameters.Length != other._parameters.Length)
return false;
// check each parameter to see if it's equal
// ...
}
public override bool Equals(object obj)
{
return Equals(obj as Parameters);
}
public override int GetHashCode()
{ ... }
#endregion
}
Create a cache for a single service. Using the wrapper class above, it should simply check if a cached result exists:
// contains cached results for a single service
class CachedCallInfo
{
private readonly Func<object[], object> _method;
private readonly Dictionary<Parameters, object> _cache
= new Dictionary<Parameters, object>();
public CachedCallInfo(Func<object[], object> method)
{
_method = method;
}
public T GetResult<T>(params object[] parameters)
{
// use out Parameters class to ensure comparison
// by value
var key = new Parameters(parameters);
object result = null;
// result exists?
if (!_cache.TryGetValue(key, out result))
{
// do the actual service call
result = _method(parameters);
// add to cache
_cache.Add(key, result);
}
return (T)result;
}
}
Create the final class which will reference services by name:
public class ServiceCache
{
private readonly Dictionary<string, CachedCallInfo> _services =
new Dictionary<string, CachedCallInfo>();
public void RegisterService(string name, Func<object[], object> method)
{
_services[name] = new CachedCallInfo(method);
}
// "params" keyword is used to simplify method calls
public T GetResult<T>(string serviceName, params object[] parameters)
{
return _services[serviceName].GetResult<T>(parameters);
}
}
Your cache setup will then look like this:
serviceCache.RegisterService("ServiceA", #params => DoSomething(#params));
serviceCache.RegisterService("ServiceB", #params => SomethingElse(#params));
And you would simply call it like this:
var result = serviceCache.GetResult("ServiceA", paramA, paramB, paramC);
Not sure why this is useful, but here goes:
public class SomeCrazyClass<T>
{
private Expression<Func<T>> _method;
public void SetExecutableMethod(Expression<Func<T>> methodParam)
{
_method = methodParam;
}
public object ExecuteMethod(SomeService someService, object[] parameterValues)
{
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
var methodCall = Expression.Call(Expression.Constant(someService), method,
parameterValues.Select(Expression.Constant));
return Expression.Lambda(methodCall).Compile().DynamicInvoke();
}
}
Call it like so:
public static void InitAndTest()
{
var something = new SomeCrazyClass<int>(); //or whatever type your method returns
var _service = new SomeService();
something.SetExecutableMethod(() => _service.SomeMethod1("param1 placeholder", "param2 placeholder"));
var result1 = something.ExecuteMethod(_service,new object[] {"Test1", "Test2"});
var result2 = something.ExecuteMethod(_service, new object[] {"Test3", "Test4"});
}
Personally, I think you're going WAY overboard, unless there is an overriding architecture need to deal with the lambda as an expression tree. But, I digress.
Instead of working with the reflective elements (which are basically for description only in terms of an expression tree), look at the Arguments member of your MethodCallExpression. It will contain several ContantExpression objects, which you can replace with your own ConstantExpressions containing the string values you want to pass in. However, Expressions are read-only; you have to rebuild an equivalent tree for this call.
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you forgot the "params" keyword
public T ExecuteMethod(params object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var arguments = methodCallExpression.Arguments;
var newArguments = new List<Expression>();
for (int i = 0; i < arguments.Count(); i++ )
{
newArguments.Add(Expression.Constant(parameterValues[i]));
}
//"Clone" the expression, specifying the new parameters instead of the old.
var newMethodExpression = Expression.Call(methodCallExpression.Object,
methodCallExpression.Method,
newArguments)
return newMethodExpression.Compile()();
}
}
...
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}
This will work as long as the expression tree can find the Func referred to by MethodCallExpression.method within the current instance.
However, I think there's a much simpler way:
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you must pass the actual array; we are creating a closure reference that will live
//as long as the delegate
public void SetMethodParams(object[] param)
{
_param = param;
}
public T ExecuteMethod(params object[] passedParam)
{
//We have to re-initialize _param based on passedParam
//instead of simply reassigning the reference, because the lambda
//requires we don't change the reference.
for(int i=0; i<_param.Length; i++)
_param[i] = passedParam.Length <= i ? null : passedParam[i];
//notice we don't pass _param; the lambda already knows about it
//via the reference set up when declaring the lambda.
return _method();
}
}
...
public void InitAndTest()
{
//this is an "external closure" we must keep in memory
object[] param = new object[2];
SetExecutableMethod( () => _service.SomeMethod1(param[0], param[1]) );
//We do so by passing the reference to our object
SetMethodParams(param);
//now, don't ever reassign the entire array.
//the ExecuteMethod function will replace indices without redefining the array.
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}
How can I get the custom attributes of a method from a Action<T> delegate?
Example:
//simple custom attribute
public class StatusAttribute : Attribute
{
public string Message { get; set; } = string.Empty;
}
// an extension methodto wrap MethodInfo.GetCustomAttributes(Type, Bool) with
// generics for the custom Attribute type
public static class MethodInfoExtentions
{
public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this MethodInfo methodInfo, bool inherit) where TAttribute : Attribute
{
object[] attributeObjects = methodInfo.GetCustomAttributes(typeof(TAttribute), inherit);
return attributeObjects.Cast<TAttribute>();
}
}
// test class with a test method to implment the custom attribute
public class Foo
{
[Status(Message="I'm doing something")]
public void DoSomething()
{
// code would go here
}
}
// creates an action and attempts to get the attribute on the action
private void CallDoSomething()
{
Action<Foo> myAction = new Action<Foo>(m => m.DoSomething());
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
// Status Attributes count = 0? Why?
}
I realize I could do this by using reflection on Foo, but for what I'm trying to create I have to use an Action<T>.
The problem is that the action doesn't directly point at Foo.DoSomething. It points at a compiler-generated method of the form:
private static void <>__a(Foo m)
{
m.DoSomething();
}
One option here would be to change it to an Expression<Action<T>>, then you can dissect the expression tree afterwards and extract the attributes:
Expression<Action<Foo>> myAction = m => m.DoSomething();
var method = ((MethodCallExpression)myAction.Body).Method;
var statusAttributes = method.GetCustomAttributes<StatusAttribute>(true);
int count = statusAttributes.Count(); // = 1
The issue is that the lambda m => m.DoSomething() is not the same as DoSomething. It is a lambda expression which gets compiled into a method call on a compiler-generated method, possibly using a compiler-generated type (though maybe not the latter, since there are no captured local variables).
A very verbose way of getting an Action<Foo> from an instance (non-static) method of the Foo type is this:
var myAction = (Action<Foo>)Delegate.CreateDelegate(
typeof(Action<Foo>),
null, // treat method as static, even though it's not
typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public)
);
Obviously, that is far from ideal and probably in fact useless in your case; but it's worth knowing ;)
Update: Actually, it just occurred to me you could write a quick extension method to make this easy for any instance method that you want to wrap as a static method (and maintain the "correct" MethodInfo):
public static class ActionEx
{
public static Action<T> ToStaticMethod<T>(this Action action)
{
if (!(action.Target is T))
{
throw new ArgumentException("Blah blah blah.");
}
return (Action<T>)Delegate.CreateDelegate(
typeof(Action<T>),
null,
action.Method
);
}
}
This would allow you to do:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>();
Admittedly, it's not as nice as m => m.DoSomething(); but it does give you an Action<T> whose Method property actually references the DoSomething method directly.
Alternately, instead of an Action<T>, you could use an Expression<Action<T>> and get the MethodInfo from that. Note that the syntax looks just the same in this case:
Action<Foo> myAction = m => m.DoSomething();
Expression<Action<Foo>> myExpression = m => m.DoSomething();
But that is a tricky proposition since an arbitrary Expression<Action<T>> is not guaranteed to be as simple as just m => m.DoSomething().
None of previous answers (except #Marc Gravell♦ 's which has no user's code) seems to be compilable :)
So I would propose mine:
private static void CallDoSomething()
{
var f = new Foo();
Action myAction = f.DoSomething;
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
}