I have got one method in class
public JObject InvokeMethod(string a_sMethod, params object[] a_params)
And I need to call this method in bool Test() in another class
protected override bool Test ()
{
logger.Write("Test1");
WebServer ws = new WebServer();
ws.InvokeMethod();
}
I need to call these two params: a_sMethod and a_params in other class.
Have anyone some idea how to do that ?
public string a_sMethod{get; set;}
does not work in this case. I get an error: There is no argument that correspondsto the required formal parameter 'a_sMethod' .
I get an error: There is no argument that correspondsto the required
formal parameter 'a_sMethod' .
error occurs here because you haven't specified the correct arguments for the method.
ws.InvokeMethod();
The method signature below expects a string and any number of data to be passed in:
public JObject InvokeMethod(string a_sMethod, params object[] a_params)
Example:
ws.InvokeMethod("testing", 1,2,3,4,5,5); // this is just for illustration, you can pass in the data you want to work with.
There are disadvantages of using object type as params array but it's beyond the scope of this question, so I will let that pass.
UPDATE
if you want to use properties, that's also simple.All you have to do is just set the data for that particular property and pass them in as the InvokeMethod(string a_sMethod, params object[] a_params) method parameters expect.
Related
I'm working with a project for thesis-work for a company and I'm having some difficulties understanding some code.
In their code they have a line like this
_subscriber.StartSubscribing(_messageHandler.HandleMessage);
where _subscriber is function is defined
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod);
And _messageHandler is defined
public void HandleMessage(QueueItem message)
{
//Do code here
}
How come at the top the messageHandler don't need a parameter for HandleMessage?
E.I
_subscriber.StartSubscribing(_messageHandler.HandleMessage(QueueItem));
Because you're not actually executing the method HandleMessage (which would happen if you had parentheses and a parameter). You are passing it as a reference to StartSubscribing which expects a method with a specified signature (void return, one parameter of type QueueItem)
Action<T> is a generic delegate, this particular version is a delegate which specifies no return (void) and a single parameter of type T (or QueueItem in your example)
In fact, it is the method StartSubscribing (or perhaps the class it belongs to) which is likely to provide the instance of QueueItem - perhaps something like this:
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod)
{
// do something to get/create a QueueItem
QueueItem item = SomeMagic();
// pass it back to the passed in delegate
messageHandlerMethod(item);
}
With _subscriber.StartSubscribing(_messageHandler.HandleMessage) you are using a more direct way for _subscriber.StartSubscribing(msg => _messageHandler.HandleMessage(msg)).
So it does need a parameter.
I am wondering if it is possible to use a classes method when you only know the classes name by it's string value.
Let's say I have a class and within class I have a static method like
public class SomeClass
{
public static string Do()
{
//Do stuff
}
}
And when using class I want to something like
string str = (GetType(SomeClass)).Do();
When using the method I want to give the name of the class as string like I want to give SomeClass as a string.
var t = Type.GetType("MyNamespace.SomeClass");
var m = t.GetMethod("Do");
m.Invoke(null, new object[] { /* Any arguments go here */ });
You're going to have to use reflection throughout; for example:
object result = Type.GetType(typeName).GetMethod(methodName).Invoke(null, args);
Use Type.GetMethod to get the method info object of the method, then call MethodInfo.Invoke to execute it. For static methods, pass null as the first parameter (the object value):
Type type = typeof(SomeClass);
type.GetMethod("Do").Invoke(null, null);
If you don’t know the class name at compile time, you can also use object.GetType, Type.GetType or Assembly.GetType to get the type object at runtime (depending on what information you have available). Then, you can use it in the same way:
Type type = someObject.GetType(); // or Type.GetType("SomeTypeName");
type.GetMethod("Do").Invoke(null, null);
To be on the safe side, make sure to check whether GetMethod actually returns a method, so you have some confirmation that the method exists on that type then.
Question:
Is it possible to know the type of parameter that is expected by the action being called? For example, I have some action as:
[TestCustomAttr]
public ActionResult TestAction(int a, string b)
{
...
and TestCustomAttr is defined as:
public class TestCustomAttr : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
...
So when the call is made to TestAction, here, inside OnActionExecuting, i want to know the type expected by the TestAction method. (e.g: in this case, there are 2 expected parameters. one is of type int and other one is of type string.
Actual Purpose:
Actually i need to make changes to the values of QueryString. I'm already able to get the querystring values (through HttpContext.Current.Request.QueryString), change it, and then manually add it to ActionParameters as filterContext.ActionParameters[key] = updatedValue;
Problem:
Currently, i try to parse the value to int, if it is successfully parsed, i assume, it is an int, so I make the require change (eg value + 1), and then add it to action parameters, against its key.
qsValue = HttpContext.Current.Request.QueryString[someKey].ToString();
if(Int32.TryParse(qsValue, out intValue))
{
//here i assume, expected parameter is of type `int`
}
else
{
//here i assume, expected parameter is of type 'string'
}
but i want to know the exact expected type. because string can be as "123", and it will be assumed to be int and added as integer parameter, causing null exception, for other parameter. (vice versa). Therefore i want to parse the updated value to exact expected type, and then add to action parameters, against its key. So, how can i do this? Is this even possible? May be Reflection can help someway?
important: I'm open to suggestions. If my approach is not good to achieve the actual purpose, or if there is a better way of doing it, please share ;)
you can get the parameter from the ActionDescriptor.
public class TestCustomAttr : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var ActionInfo = filterContext.ActionDescriptor;
var pars = ActionInfo.GetParameters();
foreach (var p in pars)
{
var type = p.ParameterType; //get type expected
}
}
}
I am loading a dll using loadfrom and iterating thru the methods to find ones that match a signature. When I find it I want to assign it as a delegate so I can call it later. This is what I am doing...
foreach (MethodInfo method in methodInfos)
{
if (method.GetParameters().Length == 2)
{
ParameterInfo[] parameters = method.GetParameters();
if (parameters[0].ParameterType.Name == "Command"
&& parameters[1].ParameterType.Name == "ExposedVariables")
{
aoc.methodinfo = method;
Command.delCmdMethod del = (Command.delCmdMethod)
Delegate.CreateDelegate(typeof(Command.delCmdMethod)
, null
, method);
}
}
}
Problem is - the delegate assignment does not work. I get an error binding to target method.
I read on the web that the the 2nd parameter could be the issue if the method is not static. My method is NOT static.
Any ideas?
Although Miky Dinescu's answer might be helpful, it is only partially correct. There does exist an overload for Delegate.CreateDelegate which will most likely help you.
First off, Miky is right that you have to pass the instance as the second parameter, but this is only the case if you want to create what is called a closed delegate. This means an instance is bound to the delegate along with the method. In practice this means when calling the delegate, it will always operate on the same instance.
From your question, it looks like that isn't what you are trying to achieve. If you want to be able to pass the instance along when calling the delegate, you have to use the CreateDelegate( Type type, MethodInfo method ) overload. This allows you to create what is called an open instance delegate.
Since you'll have to pass the instance along when calling the method, this means there is an extra parameter required in your delegate type. The first parameter of your delegate type will need to correspond to the type of the class in which the method is contained.
Example:
MethodInfo toUpperMethod
= typeof( string ).GetMethod( "ToUpper", new Type[] { } );
Func<string, string> toUpper
= (Func<string, string>)Delegate.CreateDelegate(
typeof( Func<string, string> ), toUpperMethod );
string upper = toUpper( "test" ); // Will result in "TEST".
Since - just like you - I found these overloads to be unclear, I created two helper functions to clearly separate creating a 'normal' delegate or an open instance delegate. This code, along with a more thorough discussion can be found in my blog post.
If the method is not static then you need to pass in a reference to an instance of the class who's method you are going to be invoking using the delegate.
If you don't know which instance you will be using at the time when you are attempting to create the delegate you will need to store the type and method information for later and then create the Delegate after you have the instance of the class.
EDIT
To answer your comment, the object that you need to pass is an object of the type that contains the method your are trying to bind your delegate to. So based on your code sample it's not the Command object but an object of the class from the DLL.
So, let's say that you have this .NET assembly DLL: myassembly.dll. The assembly contains the following class:
namespace MyNamespace
{
public class SomeClass
{
public SomeClass()
{
}
public void Method1(object Command, object ExposedVariables)
{
}
public void Method2(object Command, object ExposedVariables)
{
}
}
You would need to create an instance of the class SomeClass before you could create delegates bound to Method1 or Method2 of that class. So, the code which creates the delegate should look like this:
// assuming that method info is a MethodInfo contains information about the method
// that you want to create the delegate for, create an instance of the class which
// contains the method..
object classInstance = Activator.CreateInstance(methodInfo.DeclaringType);
// and then create the delegate passing in the class instance
Delegate.CreateDelegate(typeof(Command.delCmdMethod), classInstance, methodInfo);
it may be a duplicate of
How to dynamically call a class' method in .NET?
and of
how to achieve calling a function dynamically, thats right the function to be called is decided from database values, using c#
but the above two have solutions which as the answers said are complicated, not for a beginner i guess.
and
both solutions contain "type" which from the code i think is for defining the class the method belongs to.
like
static void caller(String myclass, String mymethod)
{
// Get a type from the string
Type type = Type.GetType(myclass);
// Create an instance of that type
Object obj = Activator.CreateInstance(type);
// Retrieve the method you are looking for
MethodInfo methodInfo = type.GetMethod(mymethod);
// Invoke the method on the instance we created above
methodInfo.Invoke(obj, null);
}
but my initial web site, only contains one class common to all the functions,
a database which has "function name" "func id"
supposed :- function name exactly same as that in code
i only want to achieve the following
get the string value of function name according to the id mentioned in the text box
now call that function, whose name is in the string variable
problem
the methodinfo, needs the "type.GetMethod(mymethod);"
..
In order to call a function you need to specify the type this function is declared on. If all functions you are going to call are declared on a common class you could do the following:
static void CallFunc(string mymethod)
{
// Get a type from the string
Type type = typeof(TypeThatContainsCommonFunctions);
// Create an instance of that type
object obj = Activator.CreateInstance(type);
// Retrieve the method you are looking for
MethodInfo methodInfo = type.GetMethod(mymethod);
// Invoke the method on the instance we created above
methodInfo.Invoke(obj, null);
}
If the functions you are going to call are static you don't need an instance of the type:
static void CallFunc(string mymethod)
{
// Get a type from the string
Type type = typeof(TypeThatContainsCommonFunctions);
// Retrieve the method you are looking for
MethodInfo methodInfo = type.GetMethod(mymethod);
// Invoke the method on the type
methodInfo.Invoke(null, null);
}
I see 2 solutions:
you need to map function id to
real function name
call
type.GetMethods() to get list of all
methods and choose right one