Calling a function from other class using Invoke - c#

So what i am trying to do is ;
1) I am getting a string input from user.
2) I am searching the system if project contains a function with the same name of user input.
3) If i find a function with the same name of input i am trying to execute / invoke it.
4) Usually this function is placed into another class , so i tried to create instance of class using Activators but invoke function still fails.
5) Invoke function gives me error ;
Can not invoke method : (methodName) method could not be called !
Here is the code that i am currently working on ;
public void Execute()
{
// If we are only looking for function inputs.
if (!m_canReadCls)
{
// If there is already a class linked into Developer Console.
if (s_linkedType != null)
{
MethodInfo[] tmp = ReflectionExtensions.GetFunctions(s_linkedType);
// Using linear search algorithm for executing functions.
// Need to optimize it !
if (tmp!= null)
{
string funcName = m_uProps.m_inptField.text;
int i;
for (i = 0 ;i < tmp.Length;i++)
{
if ( tmp[i].Name == funcName)
{
var instance = Activator.CreateInstance( s_linkedType);
MethodInfo m = instance.GetType().GetMethod( funcName);
Invoke(m.Name, 0.0f);
Reset();
}
}
}
}
}
}
Any help is great , thanks :-)

See Microsoft help here You can call m.Invoke. or see this post
In more details
public object Invoke(
object obj,
object[] parameters
)
and
Type magicType = Type.GetType("MagicClass");
ConstructorInfo magicConstructor = magicType.GetConstructor(Type.EmptyTypes);
object magicClassObject = magicConstructor.Invoke(new object[]{});
// Get the ItsMagic method and invoke with a parameter value of 100
MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});

Related

How to call specific function depending on a variable?

I'm generating a random number from 1-1000. I have 200 functions named function1, function4, function 10, function 11, etc. What I would like to do is execute a specific function depending on if the number generated requires a function, and ignore it if not.
My first thought was to create an int[] containing all of the values that would trigger a function, and if the int[] contains the random number to use if statements to figure out what the number is. I'm concerned that it must be a really crude solution to an easy problem though.
I know the "best way" to do something is subjective, but is there a better way to accomplish this?
UPDATE: As per comments, I should probably have started out by pointing out that doing this for 200 functions is probably a good sign that there is some serious issue in your design. This is probably an XY question where you are trying to solve a problem in some crazy way and asking about your intended solution instead of asking about the problem itself.
That said I'll leave the original answer because it's still good advice when mapping a reasonable amount of function calls that can/will change during the life cylce of your app or dynamically as the code runs.
I won't get into why you are doing this, but I'll try to at least point you in the right direction so this doesn't become a complete nightmare when you need to modify/expand behavior:
You can map numbers to function calls using delegates and a dictionary. Assuming your functions take no arguments and return void you'd do:
var functionsMap = new Dictionary<int, Action>();
//map functions
var r = getSomeRandomNumber();
if (functions.TryGetValue(r), out var a)
a(); //invoke function
Mapping functions is simply adding keys and values:
functionsMap.Add(1, () => function1());
functionsMap.Add(3, () => function3());
//etc.
If your functions take arguments or return values, you'd use the adequate delegate: Action<T>, Func<T1, T2> etc.
You can use reflection to invoke appropriate method:
Type exampleType = exampleObject.GetType();
MethodInfo exampleMethod = exampleType.GetMethod(methodName);
exampleMethod.Invoke(this, null);
Where methodName can be created using your random number.
Without commenting on the wisdom of having 200 functions named the way yours are, you can use reflection to determine whether a given functionX() exists, like so:
public void ExecuteDynamicMethod(int number)
{
// Modify these two lines with your app's dll/exe and class type:
Assembly assembly = Assembly.LoadFile("...Assembly1.dll");
Type type = assembly.GetType("YourClassType");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod("function" + number);
if (methodInfo != null)
{
object classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null); // null = "no function arguments"
}
}
}
This can then be called for a given value like
ExecuteDynamicMethod(14);
See this SO answer for the inspiration behind this.
Reflection can be used for this purpose. I want to give and keep below example for not only the objective of the question but also for future reference. Also, of course that many function is not good but below code shows the approach that can work with many functions if they have similar name (like starting with "function" keyword).
Assume below is Methods.cs
using System;
using System.Reflection;
namespace YourMethodNamespace
{
public class YourMethodClass
{
public void function1()
{
Console.WriteLine("Function-1");
}
public void function2()
{
Console.WriteLine("Function-2");
}
...
public void function200()
{
Console.WriteLine("Function-200");
}
public static void invokeMethodsDynamically(int randomNumber){
Type yourClassType = typeof(YourMethodClass);
ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(Type.EmptyTypes);
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{});
//If the constructor has parameters, then we can pass them by this way. Like below;
/*ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(new[]{typeof(int)});
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{3});
*/
MethodInfo[] methodInfoArr = yourClassType.GetMethods();
foreach(MethodInfo methodInfo in methodInfoArr){
if(methodInfo.Name == "function" + randomNumber){
methodInfo.Invoke(yourClassObject, null);
}
}
}
}
}
Let's say below is Program.cs
using System;
using YourMethodNamespace;
namespace YourProgramNamespace
{
public class YourProgramClass
{
public static void Main()
{
Random random = new Random();
int randomNumber = random.Next(1, 201);
//If Methods.cs is in another Assembly
/*string pathToDllAssembly = #"Domain.dll";
Assembly dllAssembly = Assembly.LoadFrom(pathToDllAssembly);
Type methodsClassType = dllAssembly.GetType("YourMethodNamespace.YourMethodClass");
ConstructorInfo methodClassConstructorInfo = methodsClassType.GetConstructor(Type.EmptyTypes);
object methodsClassObject = methodClassConstructorInfo.Invoke(new object[]{});
MethodInfo methodInfo = methodsClassType.GetMethod("invokeMethodsDynamically");
methodInfo.Invoke(methodsClassObject, new object[]{randomNumber});
*/
YourMethodClass.invokeMethodsDynamically(randomNumber, null);
}
}
}
Also for testing and observing, below link can be used.
https://repl.it/#erdsavasci/ReflectionTest

How to pass var as another method`s parameter?

I am making a windows application.
At first I declared var and it contains another class method.
var ExtList = ExtTarget.GetExtTargets();
And GetExtTargets() is like this
public static List<ExtTarget> GetExtTargets()
{
var dt = SqlHelper.ExecuteDataTable(QueryHelper.ConnectionString,
#"
SELECT [seq],[SourceKind],[ExtKind],[DBKind],[ConnectionString]
,[FilePath],[TableName],[FileKind],[RowSplitter],[ColumnSplitter]
,[Title],[GroupName],[SyncOrder],[RepeatKind],[RepeatMonth]
,[RepeatDay],[RepeatHour],[RepeatMin],[RepeatWeek],[RepeatWeekNum]
,[LastSyncExecDate]
FROM [ExtTarget]
order by GroupName,SyncOrder");
return dt.Rows.Cast<DataRow>().Select<DataRow, ExtTarget>(a => ExtTarget.RowToModel(a)).ToList();
}
Then, I used it to foreach and then I want to pass Ext to another method's parameter.
Code is like this.
public void ProcessExtSync(object obj)
{
while (IsProcessGoing)
{
Thread.Sleep(ThreadDelay);
if (!IsProcessGoing) return;
var ExtList = ExtTarget.GetExtTargets();
foreach (var Ext in ExtList) // I want to use this Ext as parameter
{
while (IsSourceSyncGoing)
{
Thread.Sleep(ThreadDelay);
}
IsExtSyncGoing = true;
bool ExtSyncForceToRun = ConfigSettingHelper.Instance.IsServiceConfig(Words.ExtSyncForceToRun);
bool ExtSyncForceToRunOnlyError = ConfigSettingHelper.Instance.IsServiceConfig(Words.ExtSyncForceToRunOnlyError);
bool ExtSyncNeedToRun = ConfigSettingHelper.Instance.GetNextExecutingTime(Ext) < DateTime.Now;
if (ExtSyncForceToRun || ExtSyncNeedToRun)
{
//I want to pass Ext as parameter to this method
ServiceProcess.Instance.SyncExt();
if (ExtSyncForceToRun)
{
ConfigSettingHelper.Instance.SetServiceConfig(Words.ExtSyncForceToRun, false);
}
if (ExtSyncForceToRunOnlyError)
{
ConfigSettingHelper.Instance.SetServiceConfig(Words.ExtSyncForceToRunOnlyError, false);
}
}
if (!IsProcessGoing) return;
}
IsExtSyncGoing = false;
}
}
How can I modify that code? Please help me.
var is just a shortcut way of implicitly typing a variable. It saves some typing, but sometimes makes code harder to read when the reader can't determine the type. The compiler can figure out the strong type, though (or you'll get a compiler error), and if you hover over it in Visual Studio, the compiler will tell you the actual type.
With that out of the way, all you need to do is make sure that the method you want to pass your variable to takes in the type that you want to pass it (remember the type is not var, but in your case it is an ExtTarget).
The method you're calling should have a signature similar to this (although it may return any type):
public void SyncExt(ExtTarget extTarget)
{
// Implementation code here
}
Then in your code above you can call:
ServiceProcess.Instance.SyncExt(Ext);

C# Return value from function invoked in thread

I have a calculating thread function which invokes message function from other thread using Invoke and I want that calculating thread to get value(of valuetype, like integer) from that message function. How can I do this?
The problem is that I still get old value of x variable after Invoke(...) and I expect value of 15
delegate void mes_del(object param);
void MyThreadFunc()
{
...
int x = 5;
object [] parms = new object []{x};
Invoke(new mes_del(MessageFunc), (object)parms);
...
}
void MessageFunc(object result)
{
int res = 15;
(result as object[])[0] = res;
}
I tried some approaches like using object[], object as parameters with no success. I though boxing/unboxing operations should occur in such a case but they don't.
Should I use auxiliary type like it is done in .NET event mode and create mediator object like
class holder
{
public int x;
}
int x = 5;
object [] parms = new object []{x};
What the above code does is declare a local variable, assign it the value 5, then construct an object[] array containing one element which is a copy of that local variable.
You then pass this array into your Invoke call.
I think what you'll find is that after Invoke is called, parms[0] is 15. But this does not affect x, which would actually have to be passed as a ref parameter for any method to be able to modify its local value.
What I've seen done before is something like this:
class Box<T>
{
public T Value { get; set; }
}
Then you could do:
void MyThreadFunc()
{
var x = new Box<int> { Value = 5 };
// By the way, there's really no reason to define your own
// mes_del delegate type.
Invoke(new Action<Box<int>>(MessageFunc), x);
}
void MessageFunc(Box<int> arg)
{
arg.Value = 15;
}
Are you talking about Control.Invoke from Windows Forms? If yes, the method can also return a result, so you can write:
delegate int mes_del(int param);
void MyThreadFunc() {
int x = 5;
object [] parms = new object []{x};
x = (int)Invoke(new mes_del(MessageFunc), x);
// you'll get a new value of 'x' here (incremented by 10)
}
int MessageFunc(int result) {
return result + 10;
}
Your code probably didn't work, because you were accessing x instead of picking a new value from the array (that should be modified). However, using an overload that returns a new value should be a much clearer solution.
Just return value from method
void MyThreadFunc()
{
...
int x = 5;
object [] parms = new object []{x};
var callResult = (int)Invoke((Func<object,int>)MessageFunc, (object)parms);
...
}
int MessageFunc(object result)
{
int res = 15;
return res;
}
Perhaps the best answer to your question is in .NET 4.0 System.Threading.Tasks
Here the main thread is blocked till the Result is returned by the method called on the other thread. If the result is already returned by the main thread reaches the WriteLine there is no blocking.
Task task = Task.Factory.StartNew(SomeMethod);
Console.WriteLine(task.Result);
public static string SomeMethod()
{
return "Hello World";
}
OR
Task task = Task.Factory.StartNew(() => { return "Hello World"; } );
Console.WriteLine(task.Result);
Check this blog for more interesting samples.

How do I refactor these two C# functions to abstract their logic from the specific class properties they are acting on?

I have two functions whose underlying logic is the same but in one case it sets one property value on a class and in another case it sets a different one. How can I rewrite the following two functions to abstract away as much of the algorithm as possible so that I can make changes in logic in a single place?
SetBillingAddress
private void SetBillingAddress(OrderAddress newBillingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldBillingAddress = basketHelper.Basket.Addresses[basketHelper.BillingAddressID];
bool NewBillingAddressIsNotOldBillingAddress = ((oldBillingAddress == null) || (newBillingAddress.OrderAddressId != oldBillingAddress.OrderAddressId));
bool BillingAddressHasBeenPreviouslySet = (oldBillingAddress != null);
bool BillingAddressIsNotSameAsShippingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewBillingAddressIsNotShippingAddress = (newBillingAddress.OrderAddressId != basketHelper.ShippingAddressID);
if (NewBillingAddressIsNotOldBillingAddress && BillingAddressHasBeenPreviouslySet && BillingAddressIsNotSameAsShippingAddress)
{
basketHelper.Basket.Addresses.Remove(oldBillingAddress);
}
if (NewBillingAddressIsNotOldBillingAddress && NewBillingAddressIsNotShippingAddress)
{
basketHelper.Basket.Addresses.Add(newBillingAddress);
}
basketHelper.BillingAddressID = newBillingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
And here is the second one:
SetShippingAddress
private void SetShippingAddress(OrderAddress newShippingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldShippingAddress = basketHelper.Basket.Addresses[basketHelper.ShippingAddressID];
bool NewShippingAddressIsNotOldShippingAddress = ((oldShippingAddress == null) || (newShippingAddress.OrderAddressId != oldShippingAddress.OrderAddressId));
bool ShippingAddressHasBeenPreviouslySet = (oldShippingAddress != null);
bool ShippingAddressIsNotSameAsBillingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewShippingAddressIsNotBillingAddress = (newShippingAddress.OrderAddressId != basketHelper.BillingAddressID);
if (NewShippingAddressIsNotOldShippingAddress && ShippingAddressHasBeenPreviouslySet && ShippingAddressIsNotSameAsBillingAddress)
{
basketHelper.Basket.Addresses.Remove(oldShippingAddress);
}
if (NewShippingAddressIsNotOldShippingAddress && NewShippingAddressIsNotBillingAddress)
{
basketHelper.Basket.Addresses.Add(newShippingAddress);
}
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
My initial thought was that if I could pass a class's property by refernce then I could rewrite the previous functions into something like
private void SetPurchaseOrderAddress(OrderAddress newAddress, ref String CurrentChangingAddressIDProperty)
and then call this function and pass in either basketHelper.BillingAddressID or basketHelper.ShippingAddressID as CurrentChangingAddressIDProperty but since I can't pass C# properties by reference I am not sure what to do with this code to be able to reuse the logic in both places.
Thanks for any insight you can give me.
You can pass lambda expressions:
private void SetPurchaseOrderAddress(OrderAddress newAddress, Func<string> addressIDGetter, Action<string> addressIDSetter)
Call it like this:
SetPurchaseOrderAddress(newAddress, () => basketHelper.BillingAddressID, a => basketHelper.BillingAddressID = a);
Send in a Func and an Action, one to get the property out, and another to set it again.
private void SetPurchaseOrderAddress(OrderAddress newAddress,
Func<BasketHelper, int> getAddId, Action<BasketHelper, int> setAddId) {}
Which would give something like:
SetPurchaseOrderAddress(address,
bh => bh.Basket.Addresses[bh.BillingAddressID],
(bh,s) => bh.BillingAddressID = s);
You can use delegates to create a method that takes some simple behavior (such as setting a value of the property) as an argument. In C# 3.0, you can easily create a delegate using lambda expressions and in C# 2.0 you can do similar thing using anonymous delegates.
In your example, you would write a method that takes Action<BasketHelper> delegate - the delegate allows you to specify some operation that should be done with the BasketHelper after you initialize it and before you save it:
private void SetBasketProperty(Action<BasketHelper> action) {
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
// Code that is repeated for all similar methods
// Invoke the specific action
action(basketHelper);
basketHelper.Basket.Save();
}
To call this method in C# 3.0 you can write something like this:
SetBasketProperty(basketHelper => {
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
});
The lambda expression simply provides the code that you want to run before calling Save.

How to call the correct overloaded function at runtime?

How do I call the correct overloaded function given a reference to an object based on the actual type of the object. For example...
class Test
{
object o1 = new object();
object o2 = new string("ABCD");
MyToString(o1);
MyToString(o2);//I want this to call the second overloaded function
void MyToString(object o)
{
Console.WriteLine("MyToString(object) called.");
}
void MyToString(string str)
{
Console.WriteLine("MyToString(string) called.");
}
}
what I mean is there a better option than the following?
if(typeof(o) == typeof(string))
{
MyToString((string)o);
}
else
{
MyToString(o);
}
May be this can be done using reflection?
Ok as soon as I hit post I remembered this can indeed be done using reflection...
var methInfo = typeof(Test).GetMethod("MyToString", new Type[] {o.GetType()});
methInfo.Invoke(this, new object[] {o});
You could just use ternary operators to code this using a single clean line of code:
MyToString(o is string ? (string)o : o);
Why not have a toString() function in the actual object itself? That way you can call myObj.toString() and the relative output is given. Then you don't have to do any comparisons.

Categories