Dynamically invoking any function by passing function name as string - c#

How do I automate the process of getting an instance created and its function executed dynamically?
Thanks
Edit: Need an option to pass parameters too. Thanks

Do you just want to call a parameterless constructor to create the instance? Is the type specified as a string as well, or can you make it a generic method? For example:
// All error checking omitted. In particular, check the results
// of Type.GetType, and make sure you call it with a fully qualified
// type name, including the assembly if it's not in mscorlib or
// the current assembly. The method has to be a public instance
// method with no parameters. (Use BindingFlags with GetMethod
// to change this.)
public void Invoke(string typeName, string methodName)
{
Type type = Type.GetType(typeName);
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod(methodName);
method.Invoke(instance, null);
}
or
public void Invoke<T>(string methodName) where T : new()
{
T instance = new T();
MethodInfo method = typeof(T).GetMethod(methodName);
method.Invoke(instance, null);
}

To invoke a constructor, Activator.CreateInstance will do the trick. It has a bunch of overloads to make your life easier.
If your constructor is parameterless:
object instance = Activator.CreateInstance(type)
If you need parameters:
object instance = Activator.CreateInstance(type, param1, param2)
To invoke, a method, once you have the Type object you can call GetMethod to get the method, and then Invoke (with or without parameters) to invoke it. Should you need it, Invoke will also give you the return value of the function you're calling (or null if its a void method),
For a slightly more detailed sample (paste into a console app and go):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
namespace Test
{
public static class Invoker
{
public static object CreateAndInvoke(string typeName, object[] constructorArgs, string methodName, object[] methodArgs)
{
Type type = Type.GetType(typeName);
object instance = Activator.CreateInstance(type, constructorArgs);
MethodInfo method = type.GetMethod(methodName);
return method.Invoke(instance, methodArgs);
}
}
class Program
{
static void Main(string[] args)
{
// Default constructor, void method
Invoker.CreateAndInvoke("Test.Tester", null, "TestMethod", null);
// Constructor that takes a parameter
Invoker.CreateAndInvoke("Test.Tester", new[] { "constructorParam" }, "TestMethodUsingValueFromConstructorAndArgs", new object[] { "moo", false });
// Constructor that takes a parameter, invokes a method with a return value
string result = (string)Invoker.CreateAndInvoke("Test.Tester", new object[] { "constructorValue" }, "GetContstructorValue", null);
Console.WriteLine("Expect [constructorValue], got:" + result);
Console.ReadKey(true);
}
}
public class Tester
{
public string _testField;
public Tester()
{
}
public Tester(string arg)
{
_testField = arg;
}
public void TestMethod()
{
Console.WriteLine("Called TestMethod");
}
public void TestMethodWithArg(string arg)
{
Console.WriteLine("Called TestMethodWithArg: " + arg);
}
public void TestMethodUsingValueFromConstructorAndArgs(string arg, bool arg2)
{
Console.WriteLine("Called TestMethodUsingValueFromConstructorAndArg " + arg + " " + arg2 + " " + _testField);
}
public string GetContstructorValue()
{
return _testField;
}
}
}

Assuming that the method you want to invoke does not take any parameters:
public void InvokeMethod(Type type, string methodName)
{
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
method.Invoke(instance, null);
}

I think your problem is little too generic here, I am providing a solution with certain assumptions here.
Assumption: you have a typeName (string), methodName (string), and a parameter (of SomeType).
public static void InvokeMethod(string typeName, string methodName, SomeType objSomeType) {
Type type = Type.GetType(typeName);
if(type==null) {
return;
}
object instance = Activator.CreateInstance(type); //Type must have a parameter-less contructor, or no contructor.
MethodInfo methodInfo =type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);
if(methodInfo==null) {
return;
}
methodInfo.Invoke(instance, new[] { objSomeType });
}
let me know know if my assumptions are wrong.

To pass the parameters dynamically
Here I have taken params string[] args, because different functions have different number of parameters so.
public void Invoke(string typeName,string functionName,params string[] args)
{
Type type = Type.GetType(typeName);
dynamic c=Activator.CreateInstance(type);
//args contains the parameters(only string type)
type.InvokeMember(functionName,BindingFlags.InvokeMethod,null,c,args);
}

Related

How to Invoke method in C#

From Java I've used the below code to invoke method. Pass the Instance of the class where the method is and then execute.
Context context; //Assuming the passed Instance is initialized here
Class c = Class.forName(context.getClass().getName()); //Get the class name including it's package and initialized here
Method m = c.getMethod("thisMethod", String.class, String.class); //Initialize the Method name and it's parameter type
Object t = c.newInstance();
m.invoke(t,"data1", "data2"); //Invoke the method with 2 string
I would like to convert the above code in C#. I've tried to search and I found this link and it's confused me on how can I use the instance I've passed. so far I have the below code in C#.
class Program{
static InvokerClass ic;
private static Program programInstance = new Program();
static void Main(string[] args){
ic = new InvokerClass(programInstance);
ic.StartInvokeExample("Hello","World!");
}
//Call this method later
public static void thisMethod(String data1, String data2) {
Console.WriteLine("DATA1=>" + data1 + ", DATA2=>"+data2);
}
}
class InvokerClass{
private Object objInstance;
public InvokerClass(Object obj){
this.objInstance = obj; //Get the passed Instance and use this to determine the Class Name
}
//Do invoking here
public void StartInvokeExample(String data1, String data2){
Type t = Type.GetType("? ? ?"); //I wanted to use the `objInstance` to determine the Class name
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}
From InvokerClass I would like to used the objInstance to initialize the Class name but I don't know how. And so far I don't know if I'm doing it in proper way.
This should do it for you:
class InvokerClass
{
private Object objInstance;
public InvokerClass(Object obj)
{
if (obj == null) throw new ArgumentNullException("obj must not be null");
this.objInstance = obj; //Get the passed Instance and use this to determine the Class Name
}
//Do invoking here
public void StartInvokeExample(String data1, String data2)
{
Type t = objInstance.GetType();
object classObject = Activator.CreateInstance(t);
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}
Note: you won´t need to get the constructor, simply use Activator.CreateInstance. Also take care to verify your passed object is not null to avoid a NullReferenceÈxception when trying to call objInstance.GetType().
You can pass in the object instance, but I would probably change it to use a generic instead. Although you are passing in the program object, doing it this way would provide a little more flexibility, because you don't need a an instantiated object to create a new one. You could also create an overload and get both. In your example, I would change the methods to static since you don't need an instantiated object in your example.
class Program
{
private static Program programInstance = new Program();
static void Main(string[] args)
{
InvokerClass.StartInvokeExample<Program>("Hello", "World!");
}
public static void thisMethod(String data1, String data2)
{
Console.WriteLine("DATA1=>" + data1 + ", DATA2=>" + data2);
}
}
class static InvokerClass
{
//Do invoking here
public void StartInvokeExample<T>(String data1, String data2)
where T : new()
{
Type t = typeof(T);
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
public static StartInvokeExample
(Type t, String data1, String data2)
{
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}

How to reflect a Static Public Method with Parameter passed by reference, for example Int32.TryParse

I am trying to write a generic extension method targeting .Net 4.5. I want to test a type to see if TryParse is defined in the class. If yes, invoke the TryParse method at runtime.
Here is my implemenation.
using System;
using System.Linq;
using System.Reflection;
namespace ExtentionMethodPractises
{
static public class ExtensionMethods
{
public static T ParseOrDefault<T>(this T targetType, string source) where T : new()
{
if (targetType.GetType().GetMethods(BindingFlags.Static|BindingFlags.Public).Any(methodInfo => methodInfo.Name == "TryParse"))
{
var result = new T();
var parameterTypes = new Type[] {source.GetType(), targetType.GetType()};
var parameterModifier = new ParameterModifier(2);
parameterModifier[0] = false;
parameterModifier[1] = true;
var tryParseMethod = targetType.GetType().GetMethod("TryParse", parameterTypes, new ParameterModifier[] { parameterModifier});
tryParseMethod.Invoke(null, new object[] {source, result});
return result;
}
return new T();
}
}
}
I tested my extension method with System.UInt16 which has TryParse methods. I got a nullref on the tryParseMethod after reflection.
I implemented a dummy test class ReflectorTarget to test my extension method. I got a null reference too. It seems that the reflector is incapable of search methods has pass-by-reference parameter(s).
namespace ExtentionMethodPractises
{
public class ReflectorTarget
{
public static bool TryParse(string source, out ReflectorTarget output)
{
output = new ReflectorTarget();
return true;
}
public static bool TryParse(string source, bool isReally, out ReflectorTarget output)
{
output = new ReflectorTarget();
return true;
}
}
}
Lastly, I changed my dummy test class implementation as follows. Suddenly, the reflector will pick up the TryParse method at runtime. All I did is change the second parameter from a pass-by-reference parameter to a normal parameter.
namespace ExtentionMethodPractises
{
public class ReflectorTarget
{
public static bool TryParse(string source, ReflectorTarget output)
{
return true;
}
public static bool TryParse(string source, bool isReally, out ReflectorTarget output)
{
output = new ReflectorTarget();
return true;
}
}
}
Question: How do I reflect a method (static/non-static) that has a pass-by-reference parameter in C#? Thank you.
I think you want this:
namespace ExtentionMethodPractises
{
static public class ExtensionMethods
{
public static T ParseOrDefault<T>(this T targetType, string source)
where T : new()
{
if (targetType.GetType()
.GetMethods(BindingFlags.Static|BindingFlags.Public)
.Any(methodInfo => methodInfo.Name == "TryParse"))
{
var result = new T();
var parameterTypes = new Type[] {source.GetType(),
//Key change here
targetType.GetType().MakeByRefType()};
var tryParseMethod = targetType.GetType()
.GetMethod("TryParse", parameterTypes);
tryParseMethod.Invoke(null, new object[] {source, result});
return result;
}
return new T();
}
}
}
see MakeByRefType:
Returns a Type object that represents the current type when passed as a ref parameter (ByRef parameter in Visual Basic).
tryParseMethod.Invoke(null, new object[] {source, result});
Damien got you unblocked on passing the correct type, but you still need to invoke the method correctly. A method that takes a ref argument will update the value in the passed object[], it is not going to modify your result variable. And you are interested in the return value of this method. Also notable is that ParameterModifier is actually ignored for .NET methods. Which collapses your method down to:
public static T ParseOrDefault<T>(this T targetType, string source) where T : new() {
var parameterTypes = new Type[] { source.GetType(), targetType.GetType().MakeByRefType() };
var tryParseMethod = targetType.GetType().GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, null, parameterTypes, null);
if (tryParseMethod != null) {
var args = new object[] { source, null };
var retval = (bool)tryParseMethod.Invoke(null, args);
if (retval) return (T)args[1];
}
return new T();
}

How to fill in constructor parameters in runtime?

I want to create an instance of a type, but I don't know the type until runtime.
How can I get the constructor's required parameters to display them to the user in a WPF-window?
is there something like Properties Window in Visual Studio to be used?
Have a look at the ParameterInfo objects which can be obtained from the reflected type:
Type type = typeof(T);
ConstructorInfo[] constructors = type.GetConstructors();
// take one, for example the first:
var ctor = constructors.FirstOrDefault();
if (ctor != null)
{
ParameterInfo[] params = ctor.GetParameters();
foreach(var param in params)
{
Console.WriteLine(string.Format("Name {0}, Type {1}",
param.Name,
param.ParameterType.Name));
}
}
Here is the search - http://www.bing.com/search?q=c%23+reflection+constructor+parameters - top answer is ConstructorInfo with sample:
public class MyClass1
{
public MyClass1(int i){}
public static void Main()
{
try
{
Type myType = typeof(MyClass1);
Type[] types = new Type[1];
types[0] = typeof(int);
// Get the public instance constructor that takes an integer parameter.
ConstructorInfo constructorInfoObj = myType.GetConstructor(
BindingFlags.Instance | BindingFlags.Public, null,
CallingConventions.HasThis, types, null);
if(constructorInfoObj != null)
{
Console.WriteLine("The constructor of MyClass1 that is a public " +
"instance method and takes an integer as a parameter is: ");
Console.WriteLine(constructorInfoObj.ToString());
}
else
{
Console.WriteLine("The constructor of MyClass1 that is a public instance " +
"method and takes an integer as a parameter is not available.");
}
}
catch(Exception e) // stripped out the rest of excepitions...
{
Console.WriteLine("Exception: " + e.Message);
}
}
}

How do I call a static property of a generic class with reflection?

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

How to call public functions dynamically at run time

I want to call the functions by their name at run time like
string srFunctionName="MyFunction";
So with using this variable i want to call function named as "MyFunction". How can i do that ?
You could use Reflection:
string strFunctionName = "MyFunction";
// get the type containing the method
Type t = Type.GetType("Foo.Bar.SomeTypeContainingYourFunction");
// you will need an instance of the type if the method you are
// trying to invoke is not static. If it is static you could leave that null
object instance = Activator.CreateInstance(t);
// the arguments that your method expects
new object[] arguments = new object[] { 1, "foo", false };
// invoke the method
object result = t.InvokeMember(
strFunctionName,
BindingFlags.InvokeMethod,
null,
instance,
arguments
);
UPDATE:
As requested in the comments section here's a full example with real functions:
using System;
using System.Reflection;
namespace Foo.Bar
{
public class SomeTypeContainingYourFunction
{
public string MyFunction(int foo, string bar, bool baz)
{
return string.Format("foo: {0}, bar: {1}, baz: {2}", foo, bar, baz);
}
}
}
namespace Bazinga
{
class Program
{
static void Main()
{
var strFunctionName = "MyFunction";
var t = Type.GetType("Foo.Bar.SomeTypeContainingYourFunction");
var instance = Activator.CreateInstance(t);
var arguments = new object[] { 1, "foo", false };
var result = t.InvokeMember(
strFunctionName,
BindingFlags.InvokeMethod,
null,
instance,
arguments
);
Console.WriteLine(result);
}
}
}
Here is an example to close the a form
object instance = form;
Type myType = form.GetType();
myType.InvokeMember("Close", BindingFlags.InvokeMethod, null, instance, null);
You can use reflection to create an object of a class and then call a function using that object.
object Instance = Activator.CreateInstance(t); // t is type
MethodInfo mi = t.GetMethod(srFunctionName);
if (mi != null)
mi.Invoke(Instance, args);
else
logError();

Categories