Setting parameter values of anonymous function in C# - c#

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");
}

Related

C# - In a Generic Class, How Can I Set a Generically-Typed Function Delegate?

I have a generic class of two types, "MyClass<T,U>". Based on a parameter to the class constructor, I'd like to be able to set a "Func<T,U>" local variable in a class instance that can be called to efficiently invoke a static method with input type T and output type U. The work done on the input variable depends on the input type. Can this be done?
Here's some code I've been playing with...
namespace ConsoleApp {
public class MyClass<T, U> {
// First constructor. Pass in the worker function to use.
public MyClass(Func<T, U> doWork) {
_doWork = doWork;
}
// Second constructor. Pass in a variable indicating the worker function to use.
public MyClass(int workType) {
if (workType == 1) _doWork = Workers.Method1;
else if (workType == 2) _doWork = Workers.Method2;
else throw new Exception();
}
// User-callable method to do the work.
public U DoWork(T value) => _doWork(value);
// Private instance variable with the worker delegate.
private Func<T, U> _doWork;
}
public static class Workers {
public static ushort Method1(uint value) => (ushort)(value >> 2);
public static uint Method1(ulong value) => (uint)(value >> 1);
public static ushort Method2(uint value) => (ushort)(value >> 3);
public static uint Method2(ulong value) => (uint)(value >> 4);
}
public class Program {
public static void Main(string[] args) {
var mc1 = new MyClass<uint, ushort>(Workers.Method1);
var mc2 = new MyClass<ulong, uint>(Workers.Method1);
var mc3 = new MyClass<uint, ushort>(Workers.Method2);
var mc4 = new MyClass<ulong, uint>(Workers.Method2);
var mc5 = new MyClass<uint, ushort>(1);
var mc6 = new MyClass<ulong, uint>(1);
var mc7 = new MyClass<uint, ushort>(2);
var mc8 = new MyClass<ulong, uint>(2);
}
}
}
The first constructor works just fine: the compiler is able to infer the correct overload of the static worker method to pass as a parameter, which gets stored in the instance variable _doWork, and can be (reasonably) efficiently called.
The second constructor won't compile, however, The problem is the assignments to _doWork which fail because "No overload for 'Method_' matches delegate 'Func<T,U>'". I sort of get it but sort of don't. It seems the compiler knows what T and U are at compile time, is "substituting" them into the class definition when compiling, and, so, ought to be able to infer which worker method to use. Anyone know why not?
Anyway, for reasons not worth going into, I'd really like to make the second constructor work. The obvious thing to try is to "cast" Method1 or Method2 to Func<T,U>, but delegates aren't objects and can't be cast. I've found a couple of pretty ugly ways to do it (that are also horribly inefficient), but I can't help but feeling there is something easier I'm missing. Any other ideas?
EDIT: It sounds like I'm abusing generics. What I have are about 100 different combinations of possible T, U, Worker values (there's actually a fourth dimension, but ignore that), each that behave somewhat differently. I'm trying to avoid having to create a separate class for each combination. So this isn't "generics" in the sense of being able to plug in any types T and U. What, if any, alternatives are there?
Have you considered using something like a factory pattern and resolving the service in a manner similar to this example
void Main()
{
var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, InAppNotificationMessageProcessor>();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, MessageProcessor>();
serviceCollection.AddSingleton<IMessageProcessorFactory, MessageProcessorFactory>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var factoryItem = serviceProvider.GetService<IMessageProcessorFactory>();
var service = factoryItem.Resolve(DeliveryType.Email);
service.ProcessAsync("", "", "");
}
public enum DeliveryType
{
Email,
InApp,
}
public class MessageProcessorFactory : IMessageProcessorFactory
{
private readonly IServiceProvider _serviceProvider;
public MessageProcessorFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;
public IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType)
=> _serviceProvider
.GetServices<IMessageDeliveryProcessor>()
.SingleOrDefault(processor => processor.DeliveryType.Equals(deliveryType));
}
public interface IMessageProcessorFactory
{
IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType);
}
public interface IMessageDeliveryProcessor
{
DeliveryType DeliveryType { get; }
Task ProcessAsync(string applicationId, string eventType, string messageBody);
}
public class InAppNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.InApp;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("InAppNotificationMessageProcessor");
return Task.CompletedTask;
}
}
public class EmailNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.Email;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("MessageProcessor");
return Task.CompletedTask;
}
}
This doesnt address your code and your issue exactly, but based on what I see of your issue, this could help you in the direction of travel.
In your second constructor, you are attempting to assign something not directly compatible. What you're assigning is a method group, of which nothing in the method group can match a T or a U using the compiler's type inference rules.
One thing you can do is instead of trying to assign the delegates directly in your second destructor, you can instead assign a dispatcher method that will resolve this at runtime.
Your constructor could be changed to
public MyClass(int workType)
{
if (workType == 1) _doWork = Method1Dispatcher;
else if (workType == 2) _doWork = Method2Dispatcher;
else throw new Exception();
}
where you have dispatcher methods such as
public U Method1Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method1(x),
ulong x => (U)(object)Workers.Method1(x),
_ => throw new NotSupportedException()
};
}
public U Method2Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method2(x),
ulong x => (U)(object)Workers.Method2(x),
_ => throw new NotSupportedException()
};
}
These methods use a double cast to get around the compile-time checks that prevent you from "equating", for instance, a uint and a T. Casting to object removes that constraint, and casts to another type, at runtime, could either succeed or fail. That's not typesafe, but if implemented carefully like the above, you at least encapsulate known (to us not the compiler) safe casts.
To test that this works, you can modify your Main method to prove it
var mc5 = new MyClass<uint, ushort>(1);
var mc5Result = mc5.DoWork(5);
Console.WriteLine($"Got result {mc5Result} of type {mc5Result.GetType().Name}");
var mc6 = new MyClass<ulong, uint>(1);
var mc6Result = mc6.DoWork(6);
Console.WriteLine($"Got result {mc6Result} of type {mc6Result.GetType().Name}");
var mc7 = new MyClass<uint, ushort>(2);
var mc7Result = mc7.DoWork(7);
Console.WriteLine($"Got result {mc7Result} of type {mc7Result.GetType().Name}");
var mc8 = new MyClass<ulong, uint>(2);
var mc8Result = mc8.DoWork(8);
Console.WriteLine($"Got result {mc6Result} of type {mc8Result.GetType().Name}");
Now, while this works, it's probably not the best solution because you say there are hundreds of combinations. Perhaps you can replace the switch with a reflection based way of obtaining the correct method, and then invoking it.

How can I create a delegate to read a property of an anonymous type?

I have a method that is called with an instance of an anonymous type. The type is always the same, but the instance is different.
NOTE: I am passed the anonymous object simply as a type object.
I know the anonymous type has a property named Request of type HttpRequestMessage. Here is my method that is executed with the anonymous type in info.Value.
void IObserver<KeyValuePair<string, object> event> OnNext(KeyValuePair<string, object> info)
{
HttpRequestMessage request = ?????
}
I can get the property getter like so:
MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();
But I can't afford the cost of reflection when reading the property of the instance passed to me.
How can I create a delegate that I pass the instance to and get the property value?
I tried this
private delegate HttpRequestMessage RequestPropertyGetterDelegate(object instance);
private static RequestPropertyGetterDelegate RequestPropertyGetter;
private static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();
return (RequestPropertyGetterDelegate)Delegate.CreateDelegate(typeof(RequestPropertyGetterDelegate), propertyGetter);
}
But I am experiencing a binding error
System.ArgumentException: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'
Here it is, using expression trees.
All you have to do is cache the getter, the performance should be the same as direct access.
void Main()
{
var instance = new TestClass { Request = "Something 2" };
var getter = CreateRequestFromPropertyDelegate(typeof(TestClass));
// Cache getter per type
var value = getter(instance);
Console.WriteLine(value); // Prints "Something 2"
}
private delegate string RequestPropertyGetterDelegate(object instance);
static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
// Entry of the delegate
var instanceParam = Expression.Parameter(typeof(object), "instance");
// Cast the instance from "object" to the correct type
var instanceExpr = Expression.TypeAs(instanceParam, type);
// Get the property's value
var property = type.GetProperty("Request");
var propertyExpr = Expression.Property(instanceExpr, property);
// Create delegate
var lambda = Expression.Lambda<RequestPropertyGetterDelegate>(propertyExpr, instanceParam);
return lambda.Compile();
}
class TestClass
{
// Using string here because I'm on LINQPad
public string Request { get; set; }
}
Using some expression trees it should be:
private static readonly ConcurrentDictionary<Type, Func<object, string>> extractorsCache = new ConcurrentDictionary<Type, Func<object, string>>();
public static string GetRequest(object obj)
{
Type type = obj.GetType();
Func<object, string> extractor = extractorsCache.GetOrAdd(type, BuildExtractor);
string res = extractor(obj);
return res;
}
public static Func<object, string> BuildExtractor(Type type)
{
var par = Expression.Parameter(typeof(object));
var prop = Expression.Property(Expression.TypeAs(par, type), "Request");
return Expression.Lambda<Func<object, string>>(prop, par).Compile();
}
and then:
string r1 = GetRequest(new { Request = "Foo" });
string r2 = GetRequest(new { Request = "Bar" });
string r3 = GetRequest(new { Request = "Baz" });
string r4 = GetRequest(new { Request = "Zoo", Ix = 1 });
Note that the compiled expression trees are cached in a ConcurrentDictionary<,>, so these four GetRequest will generate two compiled expressions (because in the end there are two anonymous types here).
There is no way to do this without Genric-ising the function you are writing it in. Because the anonymous type is more specific than object, an object parameter will never bind.
You can work around this by putting the whole thing in a static generic class:
static class AnonHelper<T>
{
public readonly Func<T, HttpRequestMessage> Getter = (Func<T, HttpRequestMessage>)
Delegate.CreateDelegate(
typeof(Func<T, HttpRequestMessage>, propertyGetter)),
typeof(T)
.GetProperty("Request")
.GetGetMethod()
);
}
You still cannot access it as you cannot declare the generic parameter.
So wrap it in a function on the outside (you could even make it an extension):
HttpRequestMessage GetProp<T>(T obj)
{
return AnonHelper<T>.Getter(obj);
}
You can then call it like so:
GetProp(anonObj)
This only works if you can call GetProp at the point where the type of the anonymous object is statically known, usually the same method it is declared in.

How to check if method has an attribute

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.

Creating a genericly typed Action<> at runtime

Is it possible to create a generically typed Action at run time based on some specified types? In this particular scenario, the body of the Action will ultimately ignore the argument types, as the typed Action<> will just be a wrapper around a no-argument Action, e.g.
Action original = () => { };
...
Action<TType> wrapper = (arg) => {
original();
}
Or, even:
Action<TTypeA, TTypeB> wrapper = (arg) => {
original();
}
As you can see, the body of the typed Action<> ignores the arguments, and their type, it's just acting as a wrapper.
If you're curious as to why I want create this wrapper in the first place, the 'basic' version is that I am ultimately converting the Action to a Delegate for doing a Delegate.Combine(), which requires identical types. All I am trying to accomplish with the Delegate.Combine() is a basic notification that the delegate was fired.
At this point I will probably re-work my design to avoid these types of shenanigans, but I am still very curious how this might be accomplished.
The closest I could get was the following:
private static TType GetTypedDelegate<TType>(Action onComplete)
where TType : class
{
MethodInfo info = typeof(TType).GetMethod("Invoke");
ParameterInfo[] parameters = info.GetParameters();
object result;
if (parameters.Length == 0)
result = onComplete;
else if (parameters.Length == 1)
result = GetTypedDelegate<TType>(onComplete, parameters[0].ParameterType);
// etc
TType onCompleteCasted = Delegate.CreateDelegate(typeof(TType), result, "Invoke") as TType;
return onCompleteCasted;
}
private static Delegate GetTypedDelegate<TType>(Action onComplete, Type type)
{
// This line isn't useful for me right now, since I can't just create a new
// instance of the action with a parameterless constructor ... but I thought I'd throw it in here in case it was of use
Type actionType = typeof(Action<>).MakeGenericType(new[] { type });
// Do some magic here with the type information
// The following of course does not work,but you get the idea of what I am aiming for
Action<type> wrapper = (arg1) =>
{
onComplete();
};
return wrapper as Delegate;
}
I think that the easiest option is to write a generic method and then invoke it dynamically (using Reflection or possibly even using C# 4 dynamic):
class Helper {
public static Action<TType> Wrap1<TType>(Action arg) {
return (arg) => { original(); }
}
}
Invoking the method using Reflection and using typ1 as the generic type argument could look like this:
var meth = typeof(Helper).GetMethod("Wrap1");
var gmeth = meth.MakeGenericMethod(new[] { typ1 });
var genericAction = gmeth.Invoke(null, new object[] { action });
If you don't want to use reflection you can setup some classes like this.
public class ActionWrapper<TTypeA>
{
protected readonly Action _original;
public ActionWrapper(Action original)
{
_original = original;
}
public Action<TTypeA> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a)
{
_original();
}
}
public class ActionWrapper<TTypeA,TTypeB>:ActionWrapper<TTypeA>
{
public ActionWrapper(Action original) : base(original)
{
}
public new Action<TTypeA, TTypeB> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a,TTypeB b)
{
_original();
}
}

How do I get the custom attributes of a method from Action<T>?

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);
}

Categories

Resources