I have a string whose content is name of 1 function in my WP apps. For example, assume that I have:
string functionName = "button3_Click"
So I would like to call the button3_Click() in my apps. I tried the GetRuntimeMethod method in System.Reflection but the result returned is null, so when I use invoke I got the System.NullReferenceException. My code to call this function is:
System.Type[] types = { typeof(MainPage), typeof(RoutedEventArgs) };
string functionName = "button3_Click";
System.Type thisType = this.GetType();
MethodInfo method = thisType.GetRuntimeMethod(functionName, types);
object[] parameters = {this, null};
method.Invoke(this, parameters);
And the prototype of button3_Click is:
private void button3_Click(object sender, RoutedEventArgs e)
So how can I call the function whose name contained in the string? Thank you so much for you help.
Update
I can call the button3_Click() method by changing access level of this method to public, is there any way to keep access level of this method is private and I can call this method? Thank you for your help.
Finally
I think I should use the code like this, it can get all method even its access level is private or public:
System.Type[] types = { typeof(MainPage), typeof(RoutedEventArgs) };
string functionName = "button6_Click";
TypeInfo typeinfo = typeof(MainPage).GetTypeInfo();
MethodInfo methodinfo = typeinfo.GetDeclaredMethod(functionName);
object[] parameters = {this, null};
methodinfo.Invoke(this, parameters);
Thank you for your help.
If your app is a Windows Runtime app, use GetTypeInfo extension method on thisType and then use TypeInfo.GetDeclaredMethod method:
using System.Reflection;
...
System.Type thisType = this.GetType();
TypeInfo thisTypeInfo = thisType.GetTypeInfo();
MethodInfo method = thisTypeInfo.GetDeclaredMethod(functionName);
object[] parameters = {this, null};
method.Invoke(this, parameters);
It is said in documentation that GetDeclaredMethod returns all public members of a type, but according to .NET Reference Source, the documentation seems to be incorrect: it calls Type.GetMethod with flags constant that contains BindingFlags.NonPublic.
There are restrictions on Silverlight reflection:
In Silverlight, you cannot use reflection to access private types and members. If the access level of a type or member would prevent you from accessing it in statically compiled code, you cannot access it dynamically by using reflection. (source)
Look into LambdaExpressions as it might be a workaround in this case.
Related
I have a project which reads an external DLL through reflection and
System.Reflection.Assembly BuildDll = System.Reflection.Assembly.LoadFrom(System.AppDomain.CurrentDomain.BaseDirectory + BuildDllName);
Type BuildWindow = BuildDll.GetType(BuildFormType);
System.Reflection.MethodInfo constructors = BuildWindow.GetMethod("Initialize");
lMethod = BuildWindow.GetMethod("Submit");
TypeUserControl = Activator.CreateInstance(BuildWindow);
In this code I load the DLL and read its two methods Submit(to call this method to perform some actions) & Initialize(to pass the data required by DLL)
Now I have to return a function's result from my code to the DLL on a button event of that external DLL, there is a method in my code which returns the desired integer value
int GetValue(string id, int key)
In the external DLL a delegate is been defined as
private System.Delegate _BaseFunction;
public Delegate BaseFunction
{
set { _BaseFunction= value; }
}
On button Click event of external DLL result needed to be displayed
private void btnBaseInvoke_Click(object sender, RoutedEventArgs e)
{
object[] parameters = new object[2];
parameters[0]= Convert.ToString(txtParam30.Text.Trim());
parameters[1]= Convert.ToInt32(txtParam31.Text.Trim());
object obj = _BaseFunction.DynamicInvoke(parameters);
MessageBox.Show(Convert.ToString(obj));
}
What I am not getting is how will I initialize this delegate in my code & pass these parameters to my function?
The external DLL is a bit annoying in using a System.Delegate instead of a more specific delegate, but this is still very easy to solve.
To turn your GetValue method into a delegate, you can just do something like this:
var delegate = (Func<string, int, int>)GetValue;
That's it :)
Since you're using reflection (Do you have to? Isn't there an interface you could use instead or something? Do you have to load the assembly dynamically in the first place?), you may need to manually convert the resulting delegate to Delegate (which is just another cast), but I'm not sure if even that is necessary. Just call the setter on the property and pass it the delegate and you should be fine.
Did you try MethodBase.Invoke Method (Object, Object[])?
Maybe this will help you?
The code snippet below is from an ASP.NET MVC application. It accepts all parameters from browser. I believe it's vulnerable.
I'm testing an application's security, it uses Invoke method, but accepts the Object type, method and parameters dynamically from user's input. I believe it is dangerous and I'm trying to prove it.
Do you think I can invoke Console.Write or execute some sort of arbitrary/dangerous code?
I want to try to use C# Invoke Method to write to console to prove the vulnerability. This is what I did:
static void Main(string[] args)
{
Type magicType = Type.GetType("System");
ConstructorInfo magicConstructor = magicType.GetConstructor(Type.EmptyTypes);
object magicClassObject = magicConstructor.Invoke(new object[] { });
MethodInfo magicMethod = magicType.GetMethod("Console.Write");
object magicValue = magicMethod.Invoke(magicClassObject, new object[] { 100 });
}
But it doesn't work. It says Object is not initialized. What am I missing?
System is not a type, it's a namespace. You're actually looking for System.Console, which is the console class. After that, you're looking for the WriteLine method with the proper overload, which takes an int, which is what you pass to Type.GetMethod. Only then, you can invoke the MethodInfo object using Invoke passing null as the object (as this is a static class) and the right parameter.
What you actually want is this:
Type magicType = Type.GetType("System.Console");
var method = magicType.GetMethod("WriteLine", new[] { typeof(int) });
method.Invoke(null, new object[] { 100 });
my application is currently reading in a list of methods that I need to invoke, from the Database, and putting them into strings.
I want to be able to invoke these methods by their name, and pass parameters to them.
Heres a simple example of what I want to achieve:
protected void Page_Load(object sender, EventArgs e)
{
...
...
string MethodOne = "CombineText";
string WordOne = "Hello";
string WordTwo = "World";
CombineText(WordOne, WordTwo);
}
public void CombineText(string WordOne, string WordTwo)
{
Console.WriteLine(WordOne+" "+WordTwo);
}
I've seen plenty of examples online about invoking static methods, but I can't figure out how to invoke Public Void methods by name from strings.
Does anybody have any ideas? Much Appreciated!
You can use reflection.
MethodInfo mi = this.GetType().GetMethod(MethodOne);
mi.Invoke(this, new object[] { WordOne, WordTwo };
I would recommend using a switch instead of trying to call the method based on it's name.
switch(MethodOne)
{
case "CombineText":
CombineText(WordOne, WordTwo);
break;
default:
Console.WriteLine("Invalid function: " + MethodOne);
break;
}
This has the advantage of ensuring that you only accept valid arguments, and provides a way to sanitize the inputs on a per-function basis before evaluating (maybe you want to strip spaces from WordTwo for one function, for instance, or you want to pass the longer one in as the first parameter regardless of order.).
Assuming the method is an instance method of the current type:
MethodInfo method = this.GetType().GetMethod(MethodOne);
method.Invoke(this, new[] { WordOne, WordTwo });
You need to look at reflection. You need to do something like this:
Type type = GetType();
MethodInfo method = type.GetMethod(Method);
Method.Invoke(this, new object[] { WordOne, WordTwo });
http://msdn.microsoft.com/en-us/library/8zz808e6.aspx
http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx
Given below are two methods which create a delegate to set a field in a class. One method uses generics and the other does not.
Both the methods return a delegate and they work fine. But if I try to use the delegate that has been created inside the CreateDelegate method, then the non-generic delegate 'del' works fine. I can place a breakpoint on the return statement and invoke the delegate by writting del(222). But If I try to invoke the generic delegate 'genericDel' by writting genericDel(434), it throws an exception:
Delegate 'System.Action' has some invalid arguments
Can anyone explain this quirk.
class test
{
public double fld = 0;
}
public static void Main(string[] args)
{
test tst = new test() { fld = 11 };
Type myType = typeof(test);
// Get the type and fields of FieldInfoClass.
FieldInfo[] myFieldInfo = myType.GetFields(BindingFlags.Instance | BindingFlags.Public);
var a = CreateDelegate<double>(myFieldInfo[0], tst);
var b = CreateDelegate(myFieldInfo[0], tst);
Console.WriteLine(tst.fld);
b(5.0);
Console.WriteLine(tst.fld);
a(6.0);
Console.WriteLine(tst.fld);
}
public static Action<T> CreateDelegate<T>(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(T), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<T>> expTree =
Expression.Lambda<Action<T>>(assExp,
new ParameterExpression[] { numParam });
Action<T> genericDel = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: genericDel(323)
return genericDel;
}
public static Action<double> CreateDelegate(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(double), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<double>> expTree =
Expression.Lambda<Action<double>>(assExp,
new ParameterExpression[] { numParam });
Action<double> del = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: del(977)
return del;
}
I think I understood the issue; you are having problems invoking a generic delegate from the immediate window when the compile-time type of the delegate is an open generic type.
Here's a simpler repro:
static void Main() { Test<double>(); }
static void Test<T>()
{
Action<T> genericDel = delegate { };
// Place break-point here.
}
Now, if I try executing this delegate from within the Test method (by placing a break-point and using the immediate window) like this:
genericDel(42D);
I get the following error:
Delegate 'System.Action<T>' has some invalid arguments
Note that this not an exception like you have stated, but rather the 'immediate window version' of compile-time error CS1594.
Note that such a call would have failed equally at compile-time because there is no implicit or explicit conversion from double to T.
This is debatably a shortcoming of the immediate window (it doesn't appear to be willing to use additional 'run-time knowledge' to help you out in this case), but one could argue that it is reasonable behaviour since an equivalent call made at compile-time (in source code) would also have been illegal. This does appear to be a corner case though; the immediate window is perfectly capable of assigning generic variables and executing other code that would have been illegal at compile-time. Perhaps Roslyn will make things much more consistent.
If you wish, you can work around this like so:
genericDel.DynamicInvoke(42D);
(or)
((Action<double>)(object)genericDel)(42D);
The problem is that you are trying to invoke the delegate within the scope of the method that is creating it, before 'T' is known. It is trying to convert a value type (an integer) to the generic type 'T', which is not allowed by the compiler. If you think about it, it makes sense. You should only be able to pass in T as long as you are within the scope of the method that is creating the delegate, otherwise it wouldn't really be generic at all.
You need to wait for the method to return, then use the delegate. You should have no problem invoking the delegate after its completed:
var a = CreateDelegate<double>(myFieldInfo[0], tst);
var b = CreateDelegate(myFieldInfo[0], tst);
a(434);
i would like to create a generic delegate but i only know the type while the execution.
here is the delegate that i want to create :
public delegate void MyDel<T>(T t,string msg);
and here is the method in which i want to instantiate and use the delegate
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
Delegate test = Delegate.CreateDelegate(typeof(MyDel<typeSet>, method);
where typeSet is unknow for me at the compilation.
and unfortunately, the method that i want to call is not static.
Does anyone have any idea ?
Thanks in advance
You need to create the specific delegate type using MakeGenericType:
Type template = typeof(MyDel<>);
Type specific = template.MakeGenericType(typeSet);
Delegate test = Delegate.CreateDelegate(specific, method);
I think that's what you're after...