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.
Related
I'm trying to somehow determine based on my interface what type came in and then do some validation on that type. Validation differes based on type that comes in.
public static bool RequestIsValid(IPaymentRequest preAuthorizeRequest)
{
switch (preAuthorizeRequest)
{
case
}
}
but either I can't do that with an interface or I'm not doing something that will make this work.
If I can't do that on an interface which looks like the probably because I think switch needs a concrete type, then how would I do this? Just regular if statements that check typeof?
Is that the only way?
Just for completeness:
You could also overload the method for the different implementations of IPaymentRequests and remove the one that takes the interface as parameter if you don't need a "default" handling. This is also safer because adding new implementations that apparently MIGHT require special handling do not default to something, but require another method with matching signature
public static bool RequestIsValid(PaymentRequestImplementation1 preAuthorizeRequest)
{
}
public static bool RequestIsValid(PaymentRequestImplementation2 preAuthorizeRequest)
{
}
...
If you really want to keep the method taking an IRequest you can also use reflection to call the more specific methods in case your caller casts your argument in an IRequest :
public static bool RequestIsValid(IRequest preAuthorizeRequest)
{
var member = typeof (YourType).GetMethod(
"RequestIsValid",
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null,
new [] {preAuthorizeRequest.GetType()},
null);
if (member.GetParameters()[0].ParameterType != typeof (IRequest))
{
member.Invoke(null, new[] {Convert.ChangeType(preAuthorizeRequest, preAuthorizeRequest.GetType())});
}
// default
}
You'd have to use GetType method and typeof(), but unfortunately you cannot use switch/case to make a decision:
A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type.
You can use if/else statements or prepare Dictionary<Type, Func<IPaymentRequest, bool>> and use it to perform your validation logic.
private static Dictionary<Type, Func<IInterface, bool>> _validationFunctions
= new Dictionary<Type, Func<IInterface, bool>>() {
{ typeof(ClassA), (input) => false },
{ typeof(ClassB), (input) => true }
};
public static bool RequestIsValid(IInterface preAuthorizeRequest)
{
return _validationFunctions[preAuthorizeRequest.GetType()](preAuthorizeRequest);
}
You can use is or as like this:
public static bool RequestIsValid(IPaymentRequest preAuthorizeRequest)
{
if (preAuthorizeRequest is PaymentRequestClassA)
{
var classA = (PaymentRequestClassA)preAuthorizeRequest;
// handle PaymentRequestTypeA
}
else if (preAuthorizeRequest is PaymentRequestClassB)
{
var classA = (PaymentRequestClassB)preAuthorizeRequest;
// handle PaymentRequestTypeB
}
}
Or
public static bool RequestIsValid(IPaymentRequest preAuthorizeRequest)
{
var classA = preAuthorizeRequest as PaymentRequestClassA;
var classB = preAuthorizeRequest as PaymentRequestClassB;
if (classA != null)
{
// handle PaymentRequestTypeA
}
else if (classB != null)
{
// handle PaymentRequestTypeB
}
}
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
Is it possible in Entity Framework to make a custom converter method for converting an integer into an entity through an explicit conversion?
I did some research on this, and I don't know where to start.
Here's an example of what I'm trying to do.
int activeTeacherId = 38;
Teacher activeTeacher = (Teacher)activeTeacherId;
Edit 1 After some quick research, I figured out that I probably need to do something with the EntityObject if I need everything to be truly generic and flexible. However, I'm not sure how.
Edit 2 From my own experience, I managed to create the following code. However, for obvious reasons, I can't get "this" inside a static context.
If I could just somehow get the type of the object that it's being converted into (since it's not always being converted into an EntityObject, but sometimes a Person or a Teacher), then it would theoretically work.
public class EntityObject : System.Data.Objects.DataClasses.EntityObject
{
public static explicit operator EntityObject(int id)
{
var container = ModelContainer.Instance;
var thisType = this.GetType(); //this can't be done from a static context, so how do we retrieve the type that we are converting into?
var containerType = typeof (ModelContainer);
dynamic setProperty = typeof (ModelContainer).GetProperty(thisType.Name + "Set");
ObjectSet<dynamic> set = setProperty.GetValue(container);
return set.FirstOrDefault(o => o.Id == id);
}
}
I finally did it! Based on Peter's suggestions (see his comment on my question), I have created an extension method on "int" which allows me to perform the actions I am looking for.
I'm quite proud of this algorithm since I figured out most of it myself. It involves some serious reflection stuff, dynamic creation of lambda expressions, and the evaluation of them. But it works!
Any suggestions to make it shorter or better would be appreciated.
public static class EntityObjectExtensions
{
private static int Id;
public static T ToEntity<T>(this int id) where T : class
{
lock(typeof(ModelContainer))
{
Id = id;
var container = ModelContainer.Instance;
var thisType = typeof (T);
while (thisType.BaseType != typeof (EntityObject))
{
thisType = thisType.BaseType;
}
var setProperty = typeof (ModelContainer).GetProperty(thisType.Name + "Set");
dynamic set = setProperty.GetValue(container);
var firstOrDefaultMethod =
typeof (Enumerable).GetMethods().FirstOrDefault(m => m.Name == "FirstOrDefault" && m.GetParameters().Count() == 2);
var firstOrDefaultGenericMethod = firstOrDefaultMethod.MakeGenericMethod(thisType);
var lambda = typeof (Func<,>);
var genericLambda = lambda.MakeGenericType(thisType, typeof (bool));
var lambdaParameter = (Func<T, bool>) Delegate.CreateDelegate(genericLambda, typeof(EntityObjectExtensions).GetMethod("Compare", BindingFlags.Static | BindingFlags.NonPublic));
dynamic item = firstOrDefaultGenericMethod.Invoke(null, new object[] {set, lambdaParameter});
return (T) item;
}
}
private static bool Compare(dynamic item)
{
lock (typeof(ModelContainer))
{
return item.Id == Id;
}
}
}
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);
}