I'm playing with Reflection and I would like to encapsulate a call to an instance method.
I always end up doing something like this:
methodInfo.Invoke(instance, parameters)
I wonder if there's any way to encapsulate it to something like call.Invoke(parameters), where the instance is implicit.
You can create a delegate that binds the instance.
You can do this either with the static Delegate.CreateInstance method or with the MethodInfo.CrateInstance method. The former relies on you knowing that the instance is actually a hidden first parameter to the method, so the latter may be a little more clear.
class Thing
{
int _Number;
public Thing(int number) { _Number = number; }
public int GetNumber() { return _Number; }
}
public static void Main()
{
Thing thingOne = new Thing(1);
Thing thingTwo = new Thing(2);
MethodInfo getter = typeof(Thing).GetMethod("GetNumber");
Func<int> getOne = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), thingOne, getter);
Func<int> getTwo = (Func<int>)getter.CreateDelegate(typeof(Func<int>), thingTwo);
Console.WriteLine(getOne());
Console.WriteLine(getTwo());
}
Why not simply this:
public class MethodInvoker
{
private MethodInfo _method;
private object _target;
public MethodInvoker(MethodInfo method, object target)
{
_method = method;
_target = target;
}
public object Invoke(params object[] parameters) => _method.Invoke(_target, parameters);
}
...
string s = "Hello";
var invoker = new MethodInvoker(s.GetType().GetMethod("Substring",new Type[] { typeof(int), typeof(int) }), s);
Console.WriteLine(invoker.Invoke(1,3));
You might use generics for type safety on the target or return type.
Related
How do I create a Dictionary where I can store functions?
Thanks.
I have about 30+ functions which can be executed from the user. I want to be able to execute the function this way:
private void functionName(arg1, arg2, arg3)
{
// code
}
dictionaryName.add("doSomething", functionName);
private void interceptCommand(string command)
{
foreach ( var cmd in dictionaryName )
{
if ( cmd.Key.Equals(command) )
{
cmd.Value.Invoke();
}
}
}
However, the function signature is not always the same, thus having different amount of arguments.
Like this:
Dictionary<int, Func<string, bool>>
This allows you to store functions that take a string parameter and return boolean.
dico[5] = foo => foo == "Bar";
Or if the function is not anonymous:
dico[5] = Foo;
where Foo is defined like this:
public bool Foo(string bar)
{
...
}
UPDATE:
After seeing your update it seems that you don't know in advance the signature of the function you would like to invoke. In .NET in order to invoke a function you need to pass all the arguments and if you don't know what the arguments are going to be the only way to achieve this is through reflection.
And here's another alternative:
class Program
{
static void Main()
{
// store
var dico = new Dictionary<int, Delegate>();
dico[1] = new Func<int, int, int>(Func1);
dico[2] = new Func<int, int, int, int>(Func2);
// and later invoke
var res = dico[1].DynamicInvoke(1, 2);
Console.WriteLine(res);
var res2 = dico[2].DynamicInvoke(1, 2, 3);
Console.WriteLine(res2);
}
public static int Func1(int arg1, int arg2)
{
return arg1 + arg2;
}
public static int Func2(int arg1, int arg2, int arg3)
{
return arg1 + arg2 + arg3;
}
}
With this approach you still need to know the number and type of parameters that need to be passed to each function at the corresponding index of the dictionary or you will get runtime error. And if your functions doesn't have return values use System.Action<> instead of System.Func<>.
However, the function signature is not
always the same, thus having different
amount of arguments.
Let's start with a few functions defined like this:
private object Function1() { return null; }
private object Function2(object arg1) { return null; }
private object Function3(object arg1, object arg3) { return null; }
You really have 2 viable options at your disposal:
1) Maintain type-safety by having clients call your function directly.
This is probably the best solution, unless you have very good reasons for breaking from this model.
When you talk about wanting to intercept function calls, it sounds to me like you're trying to re-invent virtual functions. There's a boat load of ways to get this sort of functionality out of the box, such as inheriting from a base class an overriding its functions.
It sounds to me like you want a class that's more of a wrapper than a derived instance of a base class, so do something like this:
public interface IMyObject
{
object Function1();
object Function2(object arg1);
object Function3(object arg1, object arg2);
}
class MyObject : IMyObject
{
public object Function1() { return null; }
public object Function2(object arg1) { return null; }
public object Function3(object arg1, object arg2) { return null; }
}
class MyObjectInterceptor : IMyObject
{
readonly IMyObject MyObject;
public MyObjectInterceptor()
: this(new MyObject())
{
}
public MyObjectInterceptor(IMyObject myObject)
{
MyObject = myObject;
}
public object Function1()
{
Console.WriteLine("Intercepted Function1");
return MyObject.Function1();
}
public object Function2(object arg1)
{
Console.WriteLine("Intercepted Function2");
return MyObject.Function2(arg1);
}
public object Function3(object arg1, object arg2)
{
Console.WriteLine("Intercepted Function3");
return MyObject.Function3(arg1, arg2);
}
}
2) OR map the input of your functions to a common interface.
This might work if all of your functions are related. For example, if you're writing a game, and all the functions do something to some part of the player or player's inventory. You'd end up with something like this:
class Interceptor
{
private object function1() { return null; }
private object function2(object arg1) { return null; }
private object function3(object arg1, object arg3) { return null; }
Dictionary<string, Func<State, object>> functions;
public Interceptor()
{
functions = new Dictionary<string, Func<State, object>>();
functions.Add("function1", state => function1());
functions.Add("function2", state => function2(state.arg1, state.arg2));
functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3));
}
public object Invoke(string key, object state)
{
Func<object, object> func = functions[key];
return func(state);
}
}
Define the dictionary and add the function reference as the value, using System.Action as the type:
using System.Collections;
using System.Collections.Generic;
public class Actions {
public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>();
public Actions() {
myActions ["myKey"] = TheFunction;
}
public void TheFunction() {
// your logic here
}
}
Then invoke it with:
Actions.myActions["myKey"]();
Hey, I hope this helps. What language are you coming from?
internal class ForExample
{
void DoItLikeThis()
{
var provider = new StringMethodProvider();
provider.Register("doSomethingAndGetGuid", args => DoSomeActionWithStringToGetGuid((string)args[0]));
provider.Register("thenUseItForSomething", args => DoSomeActionWithAGuid((Guid)args[0],(bool)args[1]));
Guid guid = provider.Intercept<Guid>("doSomethingAndGetGuid", "I don't matter except if I am null");
bool isEmpty = guid == default(Guid);
provider.Intercept("thenUseItForSomething", guid, isEmpty);
}
private void DoSomeActionWithAGuid(Guid id, bool isEmpty)
{
// code
}
private Guid DoSomeActionWithStringToGetGuid(string arg1)
{
if(arg1 == null)
{
return default(Guid);
}
return Guid.NewGuid();
}
}
public class StringMethodProvider
{
private readonly Dictionary<string, Func<object[], object>> _dictionary = new Dictionary<string, Func<object[], object>>();
public void Register<T>(string command, Func<object[],T> function)
{
_dictionary.Add(command, args => function(args));
}
public void Register(string command, Action<object[]> function)
{
_dictionary.Add(command, args =>
{
function.Invoke(args);
return null;
} );
}
public T Intercept<T>(string command, params object[] args)
{
return (T)_dictionary[command].Invoke(args);
}
public void Intercept(string command, params object[] args)
{
_dictionary[command].Invoke(args);
}
}
The following scenario would allow you to use a dictionary of elements to send in as input parameters and get the same as the output parameters.
First add the following line at the top:
using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;
Then inside your class, define the dictionary as follows:
private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){
{"getmultipledata", (input) =>
{
//DO WORKING HERE
return null;
}
},
{"runproc", (input) =>
{
//DO WORKING HERE
return null;
}
}
};
This would allow you to run these anonymous functions with a syntax similar to this:
var output = actions["runproc"](inputparam);
Why not use params object[] list for method parameters and do some validation inside either your methods (or calling logic), It will allow for a variable number of parameters.
I need to call a method, passing an int. using the following code I can fetch the method but not passing the argument. How to fix it?
dynamic obj;
obj = Activator.CreateInstance(Type.GetType(String.Format("{0}.{1}", namespaceName, className)));
var method = this.obj.GetType().GetMethod(this.methodName, new Type[] { typeof(int) });
bool isValidated = method.Invoke(this.obj, new object[1]);
public void myMethod(int id)
{
}
The new object[1] part is how you're specifying the arguments - but you're just passing in an array with a single null reference. You want:
int id = ...; // Whatever you want the value to be
object[] args = new object[] { id };
method.Invoke(obj, args);
(See the MethodBase.Invoke documentation for more details.)
Note that method.Invoke returns object, not bool, so your current code wouldn't even compile. You could cast the return value to bool, but in your example that wouldn't help at execution time as myMethod returns void.
Just pass an object with the invoke method
namespace test
{
public class A
{
public int n { get; set; }
public void NumbMethod(int Number)
{
int n = Number;
console.writeline(n);
}
}
}
class MyClass
{
public static int Main()
{
test mytest = new test();
Type myTypeObj = mytest.GetType();
MethodInfo myMethodInfo = myTypeObj.GetMethod("NumbMethod");
object[] parmint = new object[] {5};
myMethodInfo.Invoke(myClassObj, parmint);
}
}
I have a class (that I cannot modify) that simplifies to this:
public class Foo<T> {
public static string MyProperty {
get {return "Method: " + typeof( T ).ToString(); }
}
}
I would like to know how to call this method when I only have a System.Type
i.e.
Type myType = typeof( string );
string myProp = ???;
Console.WriteLinte( myMethodResult );
What I've Tried:
I know how to instantiate generics classes with reflection:
Type myGenericClass = typeof(Foo<>).MakeGenericType(
new Type[] { typeof(string) }
);
object o = Activator.CreateInstance( myGenericClass );
However, is this proper to instantiate a class since I am using the static property? How do I gain access to the method if I can't compile time cast it? (System.Object does not have a definition for static MyProperty)
Edit
I realized after posting, the class I'm working with is a property, not a method. I apologize for the confusion
The method is static, so you don't need an instance of an object. You could directly invoke it:
public class Foo<T>
{
public static string MyMethod()
{
return "Method: " + typeof(T).ToString();
}
}
class Program
{
static void Main()
{
Type myType = typeof(string);
var fooType = typeof(Foo<>).MakeGenericType(myType);
var myMethod = fooType.GetMethod("MyMethod", BindingFlags.Static | BindingFlags.Public);
var result = (string)myMethod.Invoke(null, null);
Console.WriteLine(result);
}
}
Well, you don't need an instance to call a static method:
Type myGenericClass = typeof(Foo<>).MakeGenericType(
new Type[] { typeof(string) }
);
Is OK... then, simply:
var property = myGenericClass.GetProperty("MyProperty").GetGetMethod().Invoke(null, new object[0]);
should do it.
typeof(Foo<>)
.MakeGenericType(typeof(string))
.GetProperty("MyProperty")
.GetValue(null, null);
You need something like this:
typeof(Foo<string>)
.GetProperty("MyProperty")
.GetGetMethod()
.Invoke(null, new object[0]);
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");
I've noticed that the Delegate class has a Target property, that (presumably) returns the instance the delegate method will execute on. I want to do something like this:
void PossiblyExecuteDelegate(Action<int> method)
{
if (method.Target == null)
{
// delegate instance target is null
// do something
}
else
{
method(10);
// do something else
}
}
When calling it, I want to do something like:
class A
{
void Method(int a) {}
static void Main(string[] args)
{
A a = null;
Action<int> action = a.Method;
PossiblyExecuteDelegate(action);
}
}
But I get an ArgumentException (Delegate to an instance method cannot have a null 'this') when I try to construct the delegate. Is what I want to do possible, and how can I do it?
Ahah! found it!
You can create an open instance delegate using a CreateDelegate overload, using a delegate with the implicit 'this' first argument explicitly specified:
delegate void OpenInstanceDelegate(A instance, int a);
class A
{
public void Method(int a) {}
static void Main(string[] args)
{
A a = null;
MethodInfo method = typeof(A).GetMethod("Method");
OpenInstanceDelegate action = (OpenInstanceDelegate)Delegate.CreateDelegate(typeof(OpenInstanceDelegate), a, method);
PossiblyExecuteDelegate(action);
}
}
In order to do this you would have to pass a static method to PossiblyExecuteDelegate(). This will give you a null Target.
class A
{
void Method(int a) {}
static void Method2(int a) {}
static void Main(string[] args)
{
PossiblyExecuteDelegate(A.Method2);
A a = new A();
PossiblyExecuteDelegate(a.Method);
}
}
Edit: It is possible to pass a delegate to an instance method with no target via reflection, but not using standard compiled code.
It is possible with Delegate.CreateDelegate, exactly with the overload with the signature:
CreateDelegate (Type, object, MethodInfo)
If you specify "null" for the second parameter (target)
then you have to put an extra parameter into the delegate type, that specifies the instance type, and when you invoke the delegate, the instance has to be passed as first argument, followed by the "real" parameters of the method.
class Test
{
public int AddStrings(string a, string b)
{
return int.Parse(a) + int.Parse(b);
}
static void Main()
{
var test = new Test();
var methodInfo = test.GetType().GetMethod("AddStrings");
// note the first extra parameter of the Func, is the owner type
var delegateType = typeof(Func<Test, string, string, int>);
var del = Delegate.CreateDelegate(delegateType, null, methodInfo);
var result = (int)del.DynamicInvoke(test, "39", "3");
}
}