Pass static method stored in string in c# - c#

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

Related

why reflection GetMethod return null?

I need to create an instance of object dynamically and execute one method of this instance dynamically. I am trying this code but GetMethod return null.
var className = "SomeClass";
Type[] paramTypes = { typeof(Telegram.Bot.Types.User), typeof(string[]) };
var cmd = Activator.CreateInstance(null, "mynamespace." + className);
var method = cmd.GetType().GetMethod("Execute", BindingFlags.Public|BindingFlags.Instance, null, paramTypes, null);
res = method.Invoke(cmd, new object[] { e.Message.From, args }).ToString();
and this is my SomeClass code:
public class RegisterTelegramCommand : ITelegramCommand
{
public string Message
{
get
{
return "some message";
}
}
public string Execute(Telegram.Bot.Types.User telegramUser, string[] param)
{
return param[0]+" " +param[2];
}
}
how can i solve this problem?
Activator.CreateInstance returns a ObjectHandle which needs to be unwrapped first:
var className = "RegisterTelegramCommand";
Type[] paramTypes = { typeof(object), typeof(string[]) };
var cmd = Activator.CreateInstance("ConsoleApplication4", "ConsoleApplication4." + className);
Object p = cmd.Unwrap();
var method = p.GetType().GetMethod("Execute", BindingFlags.Public | BindingFlags.Instance, null, paramTypes, null);
var res = method.Invoke(p, new object[] { null, args }).ToString();
I have putted parameter null, might be due that this issue is comming, I have check this in console code is working fine
using System;
using System.Reflection;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
var className = "RegisterTelegramCommand";
Type[] paramTypes = { typeof(object), typeof(string[]) };
var cmd = Activator.CreateInstance("ConsoleApplication4", "ConsoleApplication4." + className);
Object p = cmd.Unwrap();
var method = p.GetType().GetMethod("Execute", BindingFlags.Public | BindingFlags.Instance, null, paramTypes, null);
var res = method.Invoke(p, new object[] { null, args }).ToString();
Console.Read();
}
}
public class RegisterTelegramCommand
{
public string Message
{
get { return "a"; }
}
public string Execute(object paramObject, string[] param)
{
return param[0] + " " + param[2];
}
}
}

ILGenerator Emit : Load propertyInfo has method parameter

I'm trying to make this code in IL using ILGenerator.Emit
class Foo
{
...
}
public class TestClass
{
public static void test()
{
Type t = typeof(Foo);
foreach(PropertyInfo p in t.GetProperties())
{
GenerateVar(p.PropertyInfo);
}
}
public static object GenerateVar(Type var)
{
if (var == typeof(Int32))
{
return 5;
}
else if (var == typeof(Char))
{
return 'a';
}
return null;
}
}
This is what I've done so far, and had some complications:
MethodInfo mi = TestClass.GetType().GetMethod("GenerateVar",
BindingFlags.Public |
BindingFlags.Instance);
ILGenerator generator = mb.GetILGenerator();
LocalBuilder propertyType;
LocalBuilder TestClass = mb_gen.DeclareLocal(typeof(TestClass));
foreach (PropertyInfo pi in t.GetProperties())
{
propertyType = mb_gen.DeclareLocal(pi.PropertyType);
//loads into the stack the current PropertyType and the method class
generator.Emit(OpCodes.Ldloc, TestClass);
generator.Emit(OpCodes.LdLoc, propertyType);
//calls GenerateVar(Type var) to get a PropertyType var
generator.Emit(OpCodes.Callvirt, mi);
}
It gives me the following exception:
-> expected type: System.Type , Received type: System.String
System.String is the property type that was given by: pi.PropertyType;
What am I doing wrong?
Thanks in advance
As thehennyy comment, if you can give us the full code we will can to help better. I'm trying to help here because I guess what you try to do.
So I based here on your C# code. As I understand you want to create a method that get properties of type (Foo in your case) and foreach of them, get some value based on type.
Here is a snippet of doing it for first property of the type. To complete the code you need to emit the loop, or, like you wrote in your question, loop on the properties in your C# code and emit the code for each property one after one.
static void CallGenerateVar()
{
var dm = new DynamicMethod("CallGenerateVar", typeof(object), Type.EmptyTypes, typeof(TestClass));
MethodInfo generateVarMethod = typeof(TestClass).GetMethod("GenerateVar", BindingFlags.Public | BindingFlags.Instance);
var ilGen = dm.GetILGenerator();
var properties = ilGen.DeclareLocal(typeof(PropertyInfo[]));
var index = ilGen.DeclareLocal(typeof(int));
var propInfo = ilGen.DeclareLocal(typeof(PropertyInfo));
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldtoken, typeof(Foo));
ilGen.Emit(System.Reflection.Emit.OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public));
ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, typeof(Type).GetMethod("GetProperties", Type.EmptyTypes));
ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_0);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_1);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_0);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_1);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_2);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_0);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_2);
ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, typeof(PropertyInfo).GetMethod("get_PropertyType", BindingFlags.Instance | BindingFlags.Public));
ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, generateVarMethod);
ilGen.Emit(System.Reflection.Emit.OpCodes.Ret);
var del = (Func<object>)dm.CreateDelegate(typeof(Func<object>));
var result = del.Invoke();
}
In case our Foo type looks like this:
class Foo
{
public int MyProperty { get; set; }
}
And GenerateVar looks like this:
public object GenerateVar(Type var)
{
if (var == typeof(Int32))
{
return 5;
}
else if (var == typeof(Char))
{
return 'a';
}
return null;
}
It will print 5

C# Reflection - Casting Parameter to Type

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.

HOW TO get an overloaded private/protected method using reflection

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

Accessing the constructor by using Reflection

Assume the class is public and and the constructor is internal like as
Public class A
{
private string text;
internal A(string submittedText);
public string StrText { get; }
}
In this case how could I Access the constructor by using Reflection. What I have done so far
Type[] pTypes = new Type[1];
pTypes[0] = typeof(object);
object[] argList = new object[1];
argList[0] = "Some Text";
ConstructorInfo c = typeof(A).GetConstructor
(BindingFlags.NonPublic |
BindingFlags.Instance,
null,
pTypes,
null);
A foo = (A)c.Invoke(BindingFlags.NonPublic,
null,
argList,
Application.CurrentCulture);
But it shows an error. Any Suggestions
I think the error might casued by the GetConstructor, you passed in Object type instead of String type.
var ctr = typeof(A).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(String) }, null);
btw, if the type A itself is internal, and you know public Type B and A in the same assembly, you can try:
Type typeA = typeof(B).Assembly.GetType("Namespace.AssemblyName.A", false);
var ctr = typeA.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(String) }, null);
Try this:
Type type = typeof(A);
Type[] argTypes = new Type[] { typeof(String) };
ConstructorInfo cInfo = type.GetConstructor(argTypes);
object[] argVals = new object[] { "Some string" };
Ap = (A)cInfo.Invoke(argVals);
I got help from this site:
http://www.java2s.com/Code/CSharp/Reflection/CallGetConstructortogettheconstructor.htm
I just tried it on a sample console app, where I had an internal class and it worked.
namespace ConsoleApplication1
{
internal class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; set; }
}
}
public static void Main()
{
Type type = typeof(Person);
Type[] argTypes = new Type[] { typeof(String) };
ConstructorInfo cInfo = type.GetConstructor(argTypes);
object[] argVals = new object[] { "Some string" };
Person p = (Person)cInfo.Invoke(argVals);
}
Argument type in the constructor is string, not object. So maybe like this:
pTypes[0] = typeof(string);
You should be using Activator.CreateInstance.
you can use object o1 = Activator.CreateInstance(typeof (myclass), true); for creating a instance. no need to go through that complicated code for creating instances in the same method.

Categories