Im trying to invoke a method on a new thread in a winforms c# app. But I need the method name to come from a string.
Is it possible to do something like:
public void newThread(string MethodName)
{
new Thread(new ThreadStart(MethodName)).Start();
}
I've tried but cant seem to get this to work?
Any advice would be much appreciated.
One way of doing it can be:
public void NewThread(string MethodName, params object[] parameters)
{
var mi = this.GetType().GetMethod(MethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Task.Factory.StartNew(() => mi.Invoke(this, parameters), TaskCreationOptions.LongRunning);
}
void Print(int i, string s)
{
Console.WriteLine(i + " " + s);
}
void Dummy()
{
Console.WriteLine("Dummy Method");
}
NewThread("Print", 1, "test");
NewThread("Dummy");
I am assuming you want to call method from within class itself.
Type classType = this.GetType();
object obj = Activator.CreateInstance(classType)
object[] parameters = new object[] { _objval };
MethodInfo mi = classType.GetMethod("MyMethod");
ThreadStart threadMain = delegate () { mi.Invoke(this, parameters); };
new System.Threading.Thread(threadMain).Start();
If not replace this with class you need.
Related
How can I pass the static method with params which are stored in a string? I want to use method from another class with params. I have a dictionary depending on what folder which function should be used.
Here is main class:
foreach (string folder in folders)
{
foreach (string file in Directory.EnumerateFiles(folder))
{
//switch (folder)
//{
//}
foreach(var a in GetDictionaryToFunction())
{
string nameFolder = folder.Split('\\')[folder.Split('\\').Count() - 1];
if (a.Key == nameFolder)
{
//And here I want to use the specified method with file path as param.
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(a.Value);// +"("+ file + ")");
theMethod.Invoke(theMethod, null);
}
}
}
And I'm trying to use function from this class:
class File
{
public static void ReadPayments(string filePath)
{
string[] rows = Reader.ReadCsv(filePath);
if (rows.Count() == 0) return;
listPlatnosci.Clear();
string fileName = Path.GetFileName(filePath);
foreach (string row in rows)
{
TransformRow(row, fileName);
}
}
example dictionary: <folder, FunctionToAddValues>
ReadPayments should be define as follow:
public class ClassWithTheMethod
{
public static void ReadPayments(string folder)
{
//Whatever
}
}
And call it by using this:
MethodInfo theMethod = typeof(ClassWithTheMethod).GetMethod(a.Value, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
theMethod.Invoke(null, new object[] { a.Key }); //null for static methods
Here is code which worked for me:
MethodInfo theMethod = typeof(File).GetMethod(a.Value, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
theMethod.Invoke(null, new object[] { file });
Yeah so I set up a little TestClass to figure out what GetMethod would work to actually find the method Test(ref int i). But so far nothing worked.
[Button(nameof(Method))]
public bool whatever;
private void Test(ref int i)
{
Debug.Log("Works");
}
private void Method()
{
Type[] types = { typeof(int) };
MethodInfo methodInfo = GetType().GetMethod(nameof(Test),
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
null, types, null);
Debug.Log(methodInfo);
}
What am I supposed to do? I couldn't find anything on the web so far (for GetMethod specifically)
If you mix Eser + gcores you obtain:
private void Test(ref int i)
{
Console.WriteLine(i);
i++;
}
private void Test2(out int i)
{
i = 1000;
}
public void Method()
{
Type[] types = { typeof(int).MakeByRefType() };
MethodInfo methodInfo = GetType().GetMethod(nameof(Test), BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
int num = 10;
var pars = new object[] { num };
methodInfo.Invoke(this, pars);
Console.WriteLine(pars[0]);
MethodInfo methodInfo2 = GetType().GetMethod(nameof(Test2), BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
var pars2 = new object[1];
methodInfo2.Invoke(this, pars2);
Console.WriteLine(pars2[0]);
}
Note the typeof(int).MakeByRefType(), and the fact that the object[] array containing the parameters is modified by the invoked method. I've added a second example with out that shows that you still use .MakeByRefType(), only you don't need to initialize the object[] array with a parameter. Ah and you should use the exact BindingFlags you need, not throw every BindingFlags contained in MSDN together. Static and non-static work differently :-)
You can find the method with specified arguments' types by calling an appropriate overload of GetMethod. To make the parameter a reference type use the code:
Type[] types = { typeof(int).MakeByRefType() };
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 });
}
}
using System;
using System.Reflection;
namespace Reflection
{
class Test
{
protected void methodname(int i)
{
Console.WriteLine(("in the world of the reflection- only i"));
Console.Read();
}
protected void methodname(int i, int j)
{
Console.WriteLine(("in the world of the reflection i , j"));
Console.Read();
}
}
class Program
{
static void Main(string[] args)
{
// BindingFlags eFlags = BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public|BindingFlags.NonPublic;
BindingFlags eFlags = BindingFlags.Instance|BindingFlags.NonPublic;
Test aTest = new Test();
MethodInfo mInfoMethod = typeof(Reflection.Test).GetMethod("methodname", eFlags);
mInfoMethod.Invoke(aTest, new object[] { 10 ,20});
}
}
}
I want to call both Getmethod() overloaded methods. If i give the method name , an runtime error is thrown(ambigous method call) . How to avoid this and how each method can be called.
You have to pass types of your overloaded method, this is how reflection sorts out your desired method when there's a overload.
You can't call both the methods as it has different types of input parameter. You have to know exactly which one you exactly want to call, and pass along a Type[], for instance:
// invoking overload with two parameters
MethodInfo mInfoMethod =
typeof(Reflection.Test).GetMethod(
"methodname",
BindingFlags.Instance | BindingFlags.NonPublic,
Type.DefaultBinder,
new[] {typeof (int), typeof (int)},
null);
mInfoMethod.Invoke(aTest, new object[] { 10 ,20});
OR
// invoking overload with one parameters
MethodInfo mInfoMethod =
typeof(Reflection.Test).GetMethod(
"methodname",
vBindingFlags.Instance | BindingFlags.NonPublic,
Type.DefaultBinder,
new[] { typeof (int) },
null);
mInfoMethod.Invoke(aTest, new object[] { 10 });
Use 'GetMethods' instead to retrieve all the overloads, then pick the ones you want.
Please find a working sample below:
public class ReflectionSample
{
protected void Method(int i)
{
Console.WriteLine(string.Format("in the world of the reflection- only {0}", i));
Console.Read();
}
protected void Method(int i, int j)
{
Console.WriteLine(string.Format("in the world of the reflection {0} , {1}", i,j));
Console.Read();
}
}
class Program
{
static void Main(string[] args)
{
var eFlags = BindingFlags.Instance | BindingFlags.NonPublic;
var objType = Type.GetType("Sample.ReflectionSample");
var methods = objType.GetMethods(eFlags);
foreach (var method in methods)
{
if (method.Name == "Method")
{
Console.WriteLine("Method name is :" + method.Name);
var parameters = method.GetParameters();
int value = 10;
List<object> param = new List<object>();
for (int i = 0; i < parameters.Count(); i++)
{
param.Add(value * 5);
}
Console.WriteLine(parameters.Count());
method.Invoke(new ReflectionSample(), param.ToArray());
}
}
}
}
can u try like this
You have to specify which method you want:
class SomeType
{
void Foo(int size, string bar) { }
void Foo() { }
}
SomeType obj = new SomeType();
// call with int and string arguments
obj.GetType().GetMethod("Foo", new Type[] { typeof(int), typeof(string)).Invoke(obj, new object[] { 42, "Hello" });
// call without arguments
obj.GetType().GetMethod("Foo", new Type[0]).Invoke(obj, new object[0]);
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);
}