I'm trying to use the Convert method on functions as well as actions, so I can avoid writing duplicate methods taking in delegates of Func type. Convert method comes from Convert Action<T> to Action<object>
public class Program
{
static void Main(string[] args)
{
var program = new Program();
var mi = program.GetType().GetMethod("Function", BindingFlags.Instance | BindingFlags.Public);
// Can be any version of Func
var funcType = typeof(Func<int, int>);
// Create action delegate somehow instead
var del = mi.CreateDelegate(funcType, null);
// Or dynamically convert the Func to a corresponding Action type (in this case Action<int>)
}
// Or find a way to pass it in as a parameter here
public Action<object> Convert<T>(Action<T> action)
{
return o => action((T)o);
}
public int Function(int five)
{
return five;
}
}
I think you are looking for something like this:
public static Action<T1> IgnoreResult<T1,T2>(Func<T1,T2> func)
{
return x => func(x);
}
But for all variants of Func<T1,T2....>
I think this would work:
public static Action<TR> IgnoreResult<TR>(Delegate f)
{
return x => f.DynamicInvoke(x);
}
With usage:
var action = IgnoreResult<int>(new Func<int,int>(program.Function));
action(5);
You'll not be able to get it to infer the parameters and return type without copy and pasting the first example for all variants of Action<T1...> and Func<T1,T2...>.
I'm struggling to create instances of Action<> using the MethodInfo's I can retrieve using reflection.
Using the example below I can easily call a custom method on my objects, but I would really like to convert them to Actions.
I have tried doing it by using Delegate.CreateDelegate but I can't seem to get this to return an Action with a generic type.
Example
I have created the following interface:
interface IMyTest { } // Marker interface
interface<TInput> IMyTest : IMyTest {
void MyMethod(TInput input);
}
Then I inherit the interface in a class:
class MyClass : IMyTest<DateTime>, IMyTest<int> {
void MyMethod(DateTime input) {
// Do something
}
void MyMethod(int input) {
// Do something else
}
}
And then I create a method that uses reflection to find and call "MyMethod" from the interface instance:
void DoCallMyMethod(object target, object input) {
IEnumerable<Type> interfaces = target.GetType().GetInterfaces()
.Where(x => typeof(IMyTest).IsAssignableFrom(x) && x.IsGenericType);
foreach (Type #interface in interfaces) {
Type type = #interface.GetGenericArguments()[0];
MethodInfo method = #interface.GetMethod("MyMethod", new Type[] { type });
if (method != null) {
method.Invoke(target, new[] { input });
}
}
}
And finally I put it all together:
MyClass foo = new MyClass();
DoCallMyMethod(foo, DateTime.Now);
DoCallMyMethod(foo, 47);
What I would want
Inside DoCallMyMethod I would like MethodInfo method to be converted to a generic Action so that the result would be something like this:
Action<type> myAction = method;
But this obviously doesn't work.
I found some similar SO posts (but none that cover exactly my case) that ended up with an answer similar to this:
Action<object> action =
(Action<object>)Delegate.CreateDelegate(typeof(Action<object>), target, method);
But this doesn't work because "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
How can I get an Action with the specified type as its input type, while still retaining the object references (without new instances appearing)?
You can't create an Action<object> from one of MyMethods because the method is expecting a specific object's type (int, DateTime) and if you treat it as an Action<object> you might invoke it with objects of any type.
Since what you need is return a Action<T> there is not need to pass the input value to DoCallMyMethod method. You can pass the input type as a generic parameter:
public Action<T> DoCallMyMethod<T>(object target)
{
var #interface = typeof(IMyTest<T>);
if (#interface.IsAssignableFrom(target.GetType()))
{
var method = #interface.GetMethod("MyMethod");
if (method != null)
{
var action = Delegate.CreateDelegate(typeof(Action<T>), target, method) as Action<T>;
return action;
}
}
return null;
}
Then, use it like this:
MyClass foo = new MyClass();
var action1 = DoCallMyMethod<DateTime>(foo);
var action2 = DoCallMyMethod<int>(foo);
action1(DateTime.Now);
action2(47);
If you don't know at compile time the type of the input you can try this:
public Delegate DoCallMyMethod(object target, Type inputType)
{
var #interface = typeof(IMyTest<>).MakeGenericType(inputType);
if (#interface.IsAssignableFrom(target.GetType()))
{
var method = #interface.GetMethod("MyMethod");
if (method != null)
{
var #delegate = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(inputType), target, method);
return #delegate;
}
}
return null;
}
And use it like so:
MyClass foo = new MyClass();
var action1 = DoCallMyMethod(foo, typeof(DateTime)) as Action<DateTime>;
var action2 = DoCallMyMethod(foo, typeof(int)) as Action<int>;
action1(DateTime.Now);
action2(47);
//or
int input = 47;
var #delegate = DoCallMyMethod(foo, input.GetType());
#delegate.DynamicInvoke(input);
But if you need to returns an Action<object> you can make an action receiving an object and calling the method if the object's type is valid:
public Action<object> DoCallMyMethod(object target, Type inputType)
{
var #interface = typeof(IMyTest<>).MakeGenericType(inputType);
if (#interface.IsAssignableFrom(target.GetType()))
{
var method = #interface.GetMethod("MyMethod");
if (method != null)
{
Action<object> action = obj =>
{
if (obj.GetType().IsAssignableFrom(inputType))
method.Invoke(target, new object[] { obj });
};
return action;
}
}
return null;
}
And...
MyClass foo = new MyClass();
Action<object> action = DoCallMyMethod(foo, typeof(int));
action(47); // MyMethod(int) is called.
action("..."); // Nothing happens.
Now you have an Action<object> that calls MyMethod(int) only when an integer is passed.
I have a ConvertMethods class that can be dynamically Invoked.
public class ConvertMethods
{
public ConvertMethods()
{
Type type = typeof(ConvertMethods);
methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
}
public Type GetParameterType(string methodName)
{
foreach (var method in methodInfos) {
if (method.Name == methodName) {
return method.GetParameters()[0].GetType();
}
}
throw new MissingMethodException("ConvertMethods", methodName);
}
public Type GetReturnType(string methodName)
{
foreach (var method in methodInfos) {
if (method.Name == methodName) {
return method.ReturnType;
}
}
throw new MissingMethodException("ConvertMethods", methodName);
}
public object InvokeMethod(string methodName, object parameter)
{
foreach (var method in methodInfos) {
if (method.Name == methodName) {
return InvokeInternal(method, parameter);
}
}
throw new MissingMethodException("ConvertMethods", methodName);
}
public static TimeSpan SecondsToTimeSpan(long seconds)
{
return TimeSpan.FromSeconds(seconds);
}
private object InvokeInternal(MethodInfo method, object parameter)
{
return method.Invoke(null, new[] { parameter });
}
private MethodInfo[] methodInfos;
}
Potentially, every value that needs to be converted comes from the database as a string. I want to dynamically cast/convert it it to whatever the Parameter Type is of the Invoked method. Here is what I have:
class Program
{
static void Main(string[] args)
{
string methodName = "SecondsToTimeSpan";
string value = "10";
ConvertMethods methods = new ConvertMethods();
Type returnType = methods.GetReturnType(methodName);
Type paramType = methods.GetParameterType(methodName);
object convertedParameter = (paramType)value; // error on this line
var result = methods.InvokeMethod(methodName, convertedParameter);
Console.WriteLine(result.ToString());
}
}
How can I property convert or convert the String value to whatever type paramType contains?
object convertedParameter = TypeDescriptor.GetConverter(paramType).ConvertFromString(value);
will do what you want.
So I'm trying to create an open delegate that doesn't know the type of its target in advance. I am not sure if that explains it correctly, let me show you:
class X
{
public bool test() { return false; }
}
static void Main()
{
var x = new X();
var runtimeType = x.GetType();
var method = runtimeType.GetMethod("test");
var del = ... INSERT CODE
Console.WriteLine(del(x)); // should output False
}
While Delegate.CreateDelegate(typeof(Func<X, bool>), method); works, but I don't know the type of X at compile time. What I'd like to do, is use typeof(Func<object, bool>) but that's not possible.
I searched and found this article.
I cleaned up some of the code - here's the related bit for me:
public static class MethodInfoExtensions
{
public static Func<TArg0, TReturn> F0<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = (Func<T, TReturn>)Delegate.CreateDelegate(typeof(Func<T, TReturn>), method);
return delegate(TArg0 target) { return d((T)target); };
}
public static T DelegateForCallMethod<T>(this MethodInfo targetMethod)
{
//string creatorName = (targetMethod.ReturnType == typeof(void) ? "A" : "F") + targetMethod.GetParameters().Length.ToString();
// this will just do in my case
string creatorName = "F0";
var methodParams = targetMethod.GetParameters();
var typeGenArgs = typeof(T).GetGenericArguments();
var signature = new Type[1 + methodParams.Length + typeGenArgs.Length];
int idx = 0;
signature[idx++] = targetMethod.DeclaringType;
for (int i = 0; i < methodParams.Length; i++)
signature[idx++] = methodParams[i].ParameterType;
for (int i = 0; i < typeGenArgs.Length; i++)
signature[idx++] = typeGenArgs[i];
var mth = typeof(MethodInfoExtensions).GetMethod(creatorName, BindingFlags.NonPublic | BindingFlags.Static);
var gen = mth.MakeGenericMethod(signature);
var res = gen.Invoke(null, new object[] { targetMethod });
return (T)res;
}
}
Now I can write (in INSERT CODE area) method.DelegateForCallMethod<Func<object, bool>>(); and when I call del(x) it would execute x.test() and output False correctly!
The problem is, changing X to be a struct (which is my actual use-case) breaks it! :(
Unhandled Exception: System.Reflection.TargetInvocationException: Exception has
been thrown by the target of an invocation. ---> System.ArgumentException: Error
binding to target method. at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throw
OnBindFailure) at Vexe.Runtime.Extensions.VexeTypeExtensions.F0[T,TArg0,TReturn](MethodInfo method) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Source\Runtime\RuntimeExtensions\TypeExtensions.cs:line 24
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] argum
ents, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle
typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisib
ilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Vexe.Runtime.Extensions.VexeTypeExtensions.DelegateForCallMethod[T](Method
Info targetMethod) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Source\Runtime\RuntimeExtensions\TypeExtensions.cs:line 50
at Program.Main(String[] args) in c:\Users\vexe\Desktop\MyExtensionsAndHelpers\Solution\Test\Program2.cs:line 225
(the line is res = ...)
Any idea why this happens? and how to fix it?
Thanks!
Edit: I do not want to use MethodInfo.Invoke. The whole point here is to create a delegate that's much faster to invoke than regular reflection.
Edit: Tracking down the problem, it seems that F0 is failing to create the delegate if X is a struct - It can be verified by calling MethodInfoExtensions.F0<X, object, bool>(method); - if X was a class then no problem!
Edit: Simplified even more, it seems that Delegate.CreateDelegate(typeof(Func<X, bool>), method) fails to bind if X is struct!
Edit: Found this - pretty much the same issue. But the solution implies having a custom delegate with the argument type (in my case X) known at compile time :(
So the problem is that Delegate.CreateDelegate(typeof(Func<X, bool>), method) fails if X is a struct - according to this I should create my own delegate and pass by ref. I did that, it worked, but now it doesn't if I change back to class! It starts working again for class but not struct if I remove the ref!
So given this startup code:
class X
{
public bool test() { return false; }
}
var x = new X();
var runtimeType = x.GetType();
var method = runtimeType.GetMethod("test");
Case1 (works if X is class)
delegate TReturn MyDelegate1<TArg0, TReturn>(TArg0 obj);
var del = Delegate.CreateDelegate(typeof(MyDelegate1<X, bool>), method) as MyDelegate1<X, bool>;
Console.WriteLine(del(x));
Case2 (works if X is struct)
delegate TReturn MyDelegate2<TArg0, TReturn>(ref TArg0 obj);
var del = Delegate.CreateDelegate(typeof(MyDelegate2<X, bool>), method) as MyDelegate2<X, bool>;
Console.WriteLine(del(ref x));
Now in order to adapt the original code with this, I have to have two versions for the delegates: one with ref, another without. And inside the DelegateForCallMethod function, I see if the DeclaringType for the input method is a struct or class, and use the appropriate delegate type accordingly (which I'm not even sure if it'll work)
Might update to add code if it works.
Appreciate it if someone can explain what's going on.
Edit: Here we go - (definitely not the prettiest - I feel like I'm doing something redundant):
public delegate TReturn MethodInvoker<TArg0, TReturn>(TArg0 target);
public delegate TReturn MethodInvokerRef<TArg0, TReturn>(ref TArg0 target);
public static MethodInvoker<TArg0, TReturn> F0Class<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = Delegate.CreateDelegate(typeof(MethodInvoker<T, TReturn>), method) as MethodInvoker<T, TReturn>;
return delegate(TArg0 target)
{
return d((T)target);
};
}
public static MethodInvokerRef<TArg0, TReturn> F0Struct<T, TArg0, TReturn>(MethodInfo method)
where T : TArg0
{
var d = Delegate.CreateDelegate(typeof(MethodInvokerRef<T, TReturn>), method) as MethodInvokerRef<T, TReturn>;
return delegate(ref TArg0 target)
{
var typed = (T)target;
return d(ref typed);
};
}
public static Func<TArg0, TReturn> DelegateForCallMethod<TArg0, TReturn>(this MethodInfo targetMethod)
{
var declType = targetMethod.DeclaringType;
var signature = new Type[3]
{
declType,
typeof(TArg0),
typeof(TReturn)
};
bool isValueType = declType.IsValueType;
string delegateCreator;
if (isValueType)
delegateCreator = "F0Struct";
else
delegateCreator = "F0Class";
var mth = typeof(VexeTypeExtensions).GetMethod(delegateCreator, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
var gen = mth.MakeGenericMethod(signature);
var res = gen.Invoke(null, new object[] { targetMethod });
if (isValueType)
{
var mir = (MethodInvokerRef<TArg, TReturn>)res;
return x => mir(ref x);
}
var mi = (MethodInvoker<TArg, TReturn>)res;
return x => mi(x);
}
Usage:
var x = // ... usual startup code
var del = method.DelegateForCallMethod<object, bool>();
Console.WriteLine(del(x));
in this line:
var mth = typeof(MethodInfoExtensions).GetMethod(creatorName, BindingFlags.NonPublic | BindingFlags.Static);
make the flags appropriate for your method
I'm using similar code to create getter and setter of unknown instance type.
It uses MakeGenericType instead of MakeGenericMethod, which allows to get rid of GetMethod and Invoke in favor of Activator.CreateInstance.
using System;
using System.Reflection;
public static class GetterSetterHelper
{
abstract class Factory<T, TValue>
{
public abstract Func<T, TValue> CreateGetter(MethodInfo method);
public abstract Action<T, TValue> CreateSetter(MethodInfo method);
public static Factory<T, TValue> Create(Type runtimeType)
{
var genericType = runtimeType.IsValueType ? typeof(StructFactory<,,>) : typeof(Factory<,,>);
var factoryType = genericType.MakeGenericType(new Type[] { runtimeType, typeof(T), typeof(TValue) });
return (Factory<T, TValue>)Activator.CreateInstance(factoryType);
}
}
class Factory<TRuntime, T, TValue> : Factory<T, TValue>
where TRuntime : class, T
{
public override Func<T, TValue> CreateGetter(MethodInfo method)
{
var d = (Func<TRuntime, TValue>)Delegate.CreateDelegate(typeof(Func<TRuntime, TValue>), method);
return delegate (T target) { return d((TRuntime)target); };
}
public override Action<T, TValue> CreateSetter(MethodInfo method)
{
var d = (Action<TRuntime, TValue>)Delegate.CreateDelegate(typeof(Action<TRuntime, TValue>), method);
return delegate (T target, TValue value) { d((TRuntime)target, value); };
}
}
class StructFactory<TRuntime, T, TValue> : Factory<T, TValue>
where TRuntime : struct, T
{
delegate TValue GetterDelegate(ref TRuntime instance);
public override Func<T, TValue> CreateGetter(MethodInfo method)
{
var d = (GetterDelegate)Delegate.CreateDelegate(typeof(GetterDelegate), method);
return delegate (T target)
{
var inst = (TRuntime)target;
return d(ref inst);
};
}
public override Action<T, TValue> CreateSetter(MethodInfo method)
{
// It makes little sense to create setter which sets value to COPY of value type
// It would make sense if we use delegate like:
// void ActionRef<T, TValue(ref T inst, TValue value);
throw new NotSupportedException();
}
}
public static Func<T, TValue> CreateGetter<T, TValue>(this MethodInfo methodInfo)
{
return Factory<T, TValue>.Create(methodInfo.ReflectedType).CreateGetter(methodInfo);
}
public static Action<T, TValue> CreateSetter<T, TValue>(this MethodInfo methodInfo)
{
return Factory<T, TValue>.Create(methodInfo.ReflectedType).CreateSetter(methodInfo);
}
}
Testing code:
using System;
class Program
{
class Test
{
public int DoSomething() { return 1; }
}
struct TestStruct
{
public int DoSomething() { return 2; }
}
static void Main(string[] args)
{
var method = typeof(Test).GetMethod("DoSomething");
var getter = method.CreateGetter<object, int>();
Console.WriteLine(getter(new Test()));
var method2 = typeof(TestStruct).GetMethod("DoSomething");
var getter2 = method2.CreateGetter<object, int>();
Console.WriteLine(getter2(new TestStruct()));
Console.ReadKey();
}
}
Please look on the code below to understand my problem:
public class MyClass
{
public delegate object MyDelegate(object value);
public MyDelegate GetMethodByName(string methodName)
{
// What have to be here?
}
public object Method1(object value)
{
// some code here
}
public object Method2(object value)
{
// some code here
}
public object Method3(object value)
{
// some code here
}
}
And somewhere:
var obj = new MyClass();
MyDelegate del = obj.GetMethodByName("Method1");
var result = del(someobject);
So how can I get a method handler by its name? (c#)
var obj = new MyClass();
MyDelegate del = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), obj.GetType().GetMethod("Method1"));
var result = del(someobject);
public class MyClass
{
public delegate object MyDelegate(object value);
public MyDelegate GetMethodByName(string methodName)
{
return (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), this.GetType().GetMethod(methodName));
}
public object Method1(object value)
{
throw new NotImplementedException();
}
public object Method2(object value)
{
throw new NotImplementedException();
}
public object Method3(object value)
{
throw new NotImplementedException();
}
}
I think what you are trying to achieve here is dynamic method invocation from within C#. There are a lot of ways of getting this done to be honest. Most people would use reflection for this kind of thing but I woudl rather re-engineer the code a bit. Here is a link that might help
http://www.csharphelp.com/2006/05/dynamic-method-invocation-in-c-using-reflection/
It appears that you need to dynamically construct a delegate to a method that is retrieved by reflection. To do this, you can use the CreateDelegate method as follows.
public MyDelegate GetMethodByName(string methodName)
{
MethodInfo method = GetType().GetMethod(methodName); // use BindingFlags if method is static/non-public.
return (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), method);
}
Of course, you need to make sure that the signature of MyDelegate matches that of the given method.
public class MyClass
{
public delegate object MyDelegate(object value);
MyDelegate del1, del2, del3;
public MyClass()
{
del1 = Method1;
del2 = Method2;
del3 = Method3;
// remaining Ctr code here
}
public MyDelegate GetMethodByName(string methodName)
{
if (methodName.Equals("Method1"))
return del1;
if (methodName.Equals("Method2"))
return del2;
if (methodName.Equals("Method3"))
return del3;
return null;
}
public object Method1(object value)
{
// some code here
return null;
}
public object Method2(object value)
{
// some code here
return null;
}
public object Method3(object value)
{
// some code here
return null;
}
}
If your list of methods you want to lookup from is limited to your statically defined methods , and you dont have overloaded methods , then this solution works without the overhead of using reflection. However , if you want the solution to be generic , or work with overloaded methods , then you would go the way other posts have mentioned using reflection.
Using reflection, you could get a reference to the MethodInfo instance like this.
MethodInfo[] methodInfos = typeof(MyClass).GetMethods(BindingFlags.Public |
BindingFlags.Static);
MethodInfo method1 = methodInfos.SingleOrDefault(m => m.Name == "method1");