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 });
}
}
Related
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 created an instance called input that is of type:
public class TestInput
{
public int TesTInt { get; set; }
}
I use this in this function:
public static class TestClass
{
public static string TestFunction()
{
var testInput = new TestInput();
string res = ServicesManager.Execute<string>((object) testInput);
return res;
}
}
The Execute function is here:
public static OUT Execute<OUT>(object input)
where OUT : class
{
var method = //getting method by reflection
object[] arr = new object[] { input };
return method.Invoke(null, arr) as OUT; //Error is triggered here
}
The method that I invoke is this one:
public static string TestFunctionProxy(object[] input)
{
var serviceInput = input[0] as TestInput;
//rest of code
}
I received the error in the title. (XXX - "TestInput" type)
What's happening and what is causing this error?
Note: method is static so no instance is required for the first parameter. Please correct me if I'm wrong.
Any help is appreciated.
EDIT: Updated the question with some more code for a complete example.
You are passing the wrong arguments to the method. It wants an object[] and you are giving a simpe object. This is how to fix it:
object[] arr = new object[] { new object[] { input } };
The 'outer' object[] is the parameter for Invoke, the 'inner' array is the parameter for your method.
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 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);
}
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");
}
}