c# call functions dynamically without if else - c#

Ok, So I'm felling super lazy and I was wondering if I can call a function dynamically by a function pointer or something else somehow?
Instead of writing a bunch of if else I can put all possible functions in an array and pass which index I wan't to execute.
I was thinking of some sort of linkedlist.
eg.
//mainClass
private void initFunctionLL()
{
currNode.functionRef = this.funct1;
...
nextNode.functionRef = this.funct2;
}
private void callNext(){
currNode = currNode.Next();
currNode.execute();
}
//
//nodeClass
public void execute()
{
call myFunctionRef();
}

If your functions has the same return type and the same parameters list then you can use Func<T> or Action to make a set of delegates to this functions and call it. Example for functions without parameters which don't return a value:
private void ExecuteManyFunctions()
{
List<Action> actions = new List<Action>();
actions.Add(Foo);
actions.Add(Bar);
foreach(var func in actions)
func();
}
private void Foo() => { // some logic here }
private void Bar() => { // some logic here }
Another example for functions with integer parameter returns string:
private void ExecuteManyFunctions()
{
List<Func<string, int>> actions = new List<Func<string, int>>();
actions.Add(Foo);
actions.Add(Bar);
var results = new List<string>();
foreach(var func in actions)
results.Add(func(1));
}
private string Foo(int x) => { return x.ToString(); }
private string Bar(int y) => { return "staticResult"; }

You can add a bunch of Func or Action delegates to a list and then call each one. If your method takes no arguments and returns nothing, then use Action, if it takes one argument and returns nothing then use Action<T> wherein T specifies the type of argument. If it returns something then use Func<T>, wherein T specifies the return type. In Func<T> the last item specifies the return type and the ones before specify the argument types. Please see links at then end of my answer for more details. There are many Action and Func delegates with variable parameters. If none of them are satisfy your needs, then look into Delegate.
For example, in example below I am declaring a list which will hold a bunch of funcs which take one int and return one int. Then I am looping through and calling each one. First one multiplies the number passed to it and return the product, while the 2nd one adds the number to itself.
var funcs = new List<Func<int, int>>();
funcs.Add(x => x * x);
funcs.Add(x => x + x);
funcs.Add(x => Square(x)); // Or like this
foreach (var thisFunc in funcs)
{
thisFunc(5);
}
private static int Square(int number)
{
return number * number;
}
Please see Func and Action.

Related

System.Reflection.TargetParameterCountException when Parameter count can be dynamic

All methods in the "ProbabilitiesTheory" class accept dynamic count of parameters - it means that there can be put as many parameters as one wants. But .NET still says "System.Reflection.TargetParameterCountException" when invoking a method, that has "params" keyword in its parameters.
Here's the code:
internal static class ProbabilitiesTheory
{
static public double GetMediumValue(params double[] integers)
{ }
}
class Program
{
static void Main(string[] args)
{
MethodInfo[] methods = Type.GetType("ConsoleApplication1.ProbabilitiesTheory").GetMethods();
while (true)
{
Console.WriteLine("Write the name of the method\n");
string NameOfMethod = Console.ReadLine();
Console.WriteLine("Write the parameters of the method using the following format:
parameter1;parameter2;parameter3;parameterN\n");
string ParametersOfMethod = Console.ReadLine();
foreach (var i in methods)
{
if (i.Name == NameOfMethod)
{
object[] #parameters = (from t in ParametersOfMethod.Split(';') where t != "" select (object)Convert.ToDouble(t)).ToArray();
i.Invoke(null, #parameters); // Exception HERE
}
}
Console.WriteLine("______");
}
}
}
It is absolutely ok with LINQ expression there, i get what i need to get: object[] containing dynamic amount of double values.
How do i solve this problem?
As far as reflection is concerned, a params array is just an array with a fancy syntactical sugar. You could solve the immediate problem for most of your methods by adjusting your code like so:
double[] #parameters = (from t in ParametersOfMethod.Split(';') where t != "" select Convert.ToDouble(t)).ToArray();
i.Invoke(null, new[] { #parameters});
The gist of this is that a params array is just a single parameter at run-time, and the ability to add a variable amount of values to it is just a nicety done by the compiler.
You can confirm this with a snippet like this:
void Main()
{
var parameterCount = typeof(Test).GetMethod("Foo").GetParameters().Count();
Console.WriteLine(parameterCount); // Output: 2
}
// Define other methods and classes here
public static class Test
{
public static void Foo(double x, params double[] y)
{}
}
If you need to invoke a function that uses a params array with user provided values when the params array is not the only parameter, you're going to need to get the method parameter count and work out where the array actually starts, then wrap things accordingly.

how to pass a function to a function with different parameters and execute it c#

I have a C# app.
I have several different functions with varying return types and varying parameters passed to each function.
I know I can do this:
public object RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
But I may have 2 functions I want to pass through.
The 1st function is as this example shows. It accepts a string and returns an int. But what if I want to pass an object or no parameters at all etc?
What is the generic option here please.
thanks
#PEOPLE
I have a had a lot of good suggestions here. This is why I love this site. I need to compose myself, get a cup of tea and look thoroughly at these suggestions.
I promise I shall respond.
Thank u all!
One option is to make the function argument take no arguments:
public bool RunTheMethod(Func<int> f)
{
//... do stuff
int i = f();
//... do more stuff
return true;
}
Then, when calling RunTheMethod, you can capture other arguments in lambda expressions, like this:
var b1 = RunTheMethod(() => theFunctionThatTakesAString("foo"));
var b2 = RunTheMethod(() => theFunctionThatTakesTwoIntegers(42, 1337));
If you want to be able to vary the output type, you can make RunTheMethod generic itself, like this:
public bool RunTheMethod<T>(Func<T> f)
{
//... do stuff
T x = f();
//... do more stuff
return true;
}
At this point, however, it's a question whether it really makes sense that the input argument is a function. I've noticed that the question is tagged with functional-programming; in FP, a more idiomatic design, then, would be to simply let the method take a value:
public bool RunTheMethod<T>(T x)
{
//... do stuff
// no need to call a function to get x; you already have x
//... do more stuff
return true;
}
Then, calling the method (or function) also becomes easier:
var b1 = RunTheMethod(theFunctionThatTakesAString("foo"));
var b2 = RunTheMethod(theFunctionThatTakesTwoIntegers(42, 1337));
If you need the value to be a function because you want to be able to control when it gets evaluated, consider using Lazy<T> instead.
You actually need to execute arbitrary Action instead of Func:
public object RunTheMethod(Action myMethod)
{
//... do stuff
myMethod();
//... do more stuff
return true;
}
RunTheMethod(() => Sing("La la la"));
Maybe this codes help you.
public T Common<T>(Func<T> action)
{
//do something log or watch
try
{
return action();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
}
}
public Int32 Run(string query)
{
//Set whatever type you want. Or extend generic parameters
return Common<Int32>(() =>
{
return 1;
});
}
I think you want to call a generic method in this way:
public object Execute(MethodInfo mi, object instance = null, object[] parameters = null)
{
return mi.Invoke(instance, parameters);
}
So you're method will need to take these as parameters.

How can I pass several methods (with parameters) AS a parameter?

Suppose I have the following WCF code:
try
{
ServiceClient proxy = new ServiceClient();
proxy.ClientCredentials.UserName.UserName = "user";
proxy.ClientCredentials.UserName.Password = "password";
proxy.GetData(2);
if (proxy.State = CommunicationState.Opened)
{
proxy.GetData("data");
}
proxy.Close();
}
catch (FaultException ex)
{
// handle the exception
}
And since I notice that the try...catch and other logic is repetitive, not to mention that setting up a WCF call is expensive, I want to send many "methods and parameters" to this function.
In essence pass GetData(2) and GetData("data") as a method array, and have the results return either asynchronously or synchronously.
How would I accomplish this?
I suppose I could have two 'ref' objects to handle the results[] and a shared lock to the results[]. However I'm not sure how to pass "methods with parameters" as a parameter to another function.
Perhaps another way of looking at this might be an array of function pointers, to the same function with different params.
Can anyone nudge me into the right way of doing this?
More info:
I am asking this question so I can optimize this approach to handling WCF exceptions and retries but so I don't have to always open/close the client after each call.
Use delegates and pass them in a list.
The C# Func<T> delegate is used when a return value is needed.
List<Func<Data>> funcList = new List<Func<Data>>();
funcList.Add( () => GetData(2) );
// You can use any condition as you otherwise would to add to the list.
if (proxy.State = CommunicationState.Opened)
{
funcList.Add( () => GetData("data") );
}
List<Data> ProcessFuncs(List<Func<Data>> funcDatas)
{
List<Data> returnList = new List<Data>();
foreach(var func in funcDatas)
{
returnList.Add(func());
}
}
( as long as the return types are identical, this will work )
This is just an example of course; if your methods don't return anything, you can use the C# Action delegate, which just executes an action and doesn't return any value.
List<Action> actionList = new List<Action>();
actionList.Add( () => ProcessData("data")); // ProcessData is a void with no return type
actionList.Add( () => ProcessData(2));
public void ProcessActions(List<Action> actions)
{
foreach(var action in actions)
{
action();
}
}
In response to some comments:
This code compiles and is all equivalent:
class Program
{
public static string GetData(string item) { return item; }
public static string GetData(int item) { return item.ToString(); }
static void Main(string[] args)
{
string someLocalVar = "what is it?";
int someLocalValueType = 3;
Func<string> test = () =>
{
return GetData(someLocalVar);
};
Func<string> test2 = () => GetData(someLocalValueType);
someLocalValueType = 5;
List<Func<string>> testList = new List<Func<string>>();
testList.Add(() => GetData(someLocalVar));
testList.Add(() => GetData(2));
testList.Add(test);
testList.Add(test2);
someLocalVar = "something else";
foreach(var func in testList)
{
Console.WriteLine(func());
}
Console.ReadKey();
}
}
Result is:
I wouldn't use delegates here because then you are constrained by types and to solve that it becomes horrible and over-complicated. I would just have a callback that gives you free reign over the ServiceClient once it has been set up. I think this is a pattern that has a name but I don't know.
interface IProxyActionCallback
{
void DoProxyStuff(ServiceClient proxy);
}
void MyMethod(IProxyActionCallback callback)
{
try
{
ServiceClient proxy = new ServiceClient();
proxy.ClientCredentials.UserName.UserName = "user";
proxy.ClientCredentials.UserName.Password = "password";
callback.DoProxyStuff(proxy);
proxy.Close();
}
catch (FaultException ex)
{
// handle the exception
}
}
Then you call the method like:
MyMethod(new DoSpecificStuff());
Where DoSpecificStuff is a class that implements the interface and allows you to do specific calls with the proxy:
class DoSpecificStuff : IProxyActionCallback
{
public void DoProxyStuff(ServiceClient proxy)
{
proxy.GetData(2);
if (proxy.State = CommunicationState.Opened)
{
proxy.GetData("data");
}
}
}
So you'd have tons of classes that implement the interface, and they all "share" the same try-catch boiler-plate proxy stuff which is in one place.
Bellow is an example of how to make a collection of delegates and their arguments then invoke them later on without knowing the methods definition. As far as I know if you want to invoke methods with different definitions in a single general call you have to do something like this.
List<Tuple<delegate, object[]>> delegates = new List<Tuple<delegate, object[]>>();
delegates.Add(new Tuple<delegate, object[]>(new Func<Arg1Type, Arg2Type, ReturnType>(MyFunctionName), new object[] { arg1, arg2 });
foreach (Tuple<delegate, object[]> d in delegates)
{
d.Item1.DynamicInvoke(d.Item2);
}
You could use C# delegates:
A delegate is a type that represents references to methods with a
particular parameter list and return type. When you instantiate a
delegate, you can associate its instance with any method with a
compatible signature and return type. You can invoke (or call) the
method through the delegate instance. Delegates are used to pass
methods as arguments to other methods. Event handlers are nothing more
than methods that are invoked through delegates. You create a custom
method, and a class such as a windows control can call your method
when a certain event occurs. The following example shows a delegate
declaration:
More on this:
http://msdn.microsoft.com/en-us/library/ms173171.aspx
You can pass functions with parameters this way:
public void strategy<R, T1, T2>(Func<R, T1, T2> f);
public bool predicate(string a, string b);
strategy<bool, string, string>(predicate);
The first line declares the function strategy() accepting a function f;
That function return the type R and takes two parameters of type T1 and T2.
The second line defines a function that returns a bool and accepts two string.
The third line invokes the strategy passing it the predicate as a parameter.
Not sure to understand what you're trying to achieve, but basically if your service exposes a GetData(int) method and a GetData(string) method as well as an async proxy, you should call both asynchronously using something like:
var getData = proxy.GetDataAsync(2);
var getData2 = proxy.GetDataAsync("data");
await Task.WhenAll(getData, getData2);
// Gets the result using getData.Result...etc.

Setting parameter values of anonymous function in C#

Lets say i have the following code
private Func<T> _method;
public void SetExecutableMethod<T>(Func<T> methodParam)
{
_method = methodParam;
}
public T ExecuteMethod(object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
ParameterInfo[] methodParams = method.GetParameters();
//So i now have a list of parameters for the method call,
//How can i update the parameter values for each of these?
for (int i = 0; i < parameters.Count(); i++ )
{
methodParams[i] = ???''
}
return _method.Compile()();
}
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod(new object[]{"Test1", "Test2"});
T result2 = ExecuteMethod(new object[]{"Test3", "Test4"}););
}
In the above code, i want to set a private variable to some Func that points to an anonymoust function and never have to set it again.
I then would like to be able to call ExecuteMethod(...) with different parameters. This method should update the parameter values of the variable _method and then invoke the method.
I can read the number of parameters and their values fine, i just am not sure how to set the values for those parameter? Any thoughts on this?
This is not the way to do it. Right now, your _method field is a delegate of type Func<T>, and you expect that its body contains yet another method which is actually executed. That is a lot to expect from your callers. I would forget about this approach and look for something different.
One way would be to supply a method which takes an array of objects as its parameter (Func<object[], T>), and then invoke it directly with appropriate parameters (but never a method in its body). Even this is less common for a strongly typed language like C# since you lose all type safety (but then again, you do want to be pretty flexible with this framework you are designing).
The other way would be to get a MethodInfo instance, and then use its Invoke method. In a way, this might even express your intents better, because it will be obvious that the executable method is capable of virtually anything.
Next, you could use generics to get some type safety, and require that all your input parameters are wrapped inside a single parameter class. In that case, you might have a strongly typed Func<Tparam, Tresult> method, and your Execute method would accept a Tparam instance as its parameter. This would void the need for any reflection.
[Edit]
As I wrote, I would try to avoid reflection. Since you wrote you basically need a cache of method results, a simple approach might be something like:
Create a wrapper for your list of parameters so that you can compare them "by value". I added an example class, but you might even want to allow passing an IEqualityComparer explicitly, so that you don't have to override Equals for each partial parameter.
// implements `IEquatable` for a list of parameters
class Parameters : IEquatable<Parameters>
{
private readonly object[] _parameters;
public Parameters(object[] parms)
{
_parameters = parms;
}
#region IEquatable<Parameters> Members
public bool Equals(Parameters other)
{
if (other == null)
return false;
if (_parameters.Length != other._parameters.Length)
return false;
// check each parameter to see if it's equal
// ...
}
public override bool Equals(object obj)
{
return Equals(obj as Parameters);
}
public override int GetHashCode()
{ ... }
#endregion
}
Create a cache for a single service. Using the wrapper class above, it should simply check if a cached result exists:
// contains cached results for a single service
class CachedCallInfo
{
private readonly Func<object[], object> _method;
private readonly Dictionary<Parameters, object> _cache
= new Dictionary<Parameters, object>();
public CachedCallInfo(Func<object[], object> method)
{
_method = method;
}
public T GetResult<T>(params object[] parameters)
{
// use out Parameters class to ensure comparison
// by value
var key = new Parameters(parameters);
object result = null;
// result exists?
if (!_cache.TryGetValue(key, out result))
{
// do the actual service call
result = _method(parameters);
// add to cache
_cache.Add(key, result);
}
return (T)result;
}
}
Create the final class which will reference services by name:
public class ServiceCache
{
private readonly Dictionary<string, CachedCallInfo> _services =
new Dictionary<string, CachedCallInfo>();
public void RegisterService(string name, Func<object[], object> method)
{
_services[name] = new CachedCallInfo(method);
}
// "params" keyword is used to simplify method calls
public T GetResult<T>(string serviceName, params object[] parameters)
{
return _services[serviceName].GetResult<T>(parameters);
}
}
Your cache setup will then look like this:
serviceCache.RegisterService("ServiceA", #params => DoSomething(#params));
serviceCache.RegisterService("ServiceB", #params => SomethingElse(#params));
And you would simply call it like this:
var result = serviceCache.GetResult("ServiceA", paramA, paramB, paramC);
Not sure why this is useful, but here goes:
public class SomeCrazyClass<T>
{
private Expression<Func<T>> _method;
public void SetExecutableMethod(Expression<Func<T>> methodParam)
{
_method = methodParam;
}
public object ExecuteMethod(SomeService someService, object[] parameterValues)
{
var methodCallExpression = _method.Body as MethodCallExpression;
var method = methodCallExpression.Method;
var methodCall = Expression.Call(Expression.Constant(someService), method,
parameterValues.Select(Expression.Constant));
return Expression.Lambda(methodCall).Compile().DynamicInvoke();
}
}
Call it like so:
public static void InitAndTest()
{
var something = new SomeCrazyClass<int>(); //or whatever type your method returns
var _service = new SomeService();
something.SetExecutableMethod(() => _service.SomeMethod1("param1 placeholder", "param2 placeholder"));
var result1 = something.ExecuteMethod(_service,new object[] {"Test1", "Test2"});
var result2 = something.ExecuteMethod(_service, new object[] {"Test3", "Test4"});
}
Personally, I think you're going WAY overboard, unless there is an overriding architecture need to deal with the lambda as an expression tree. But, I digress.
Instead of working with the reflective elements (which are basically for description only in terms of an expression tree), look at the Arguments member of your MethodCallExpression. It will contain several ContantExpression objects, which you can replace with your own ConstantExpressions containing the string values you want to pass in. However, Expressions are read-only; you have to rebuild an equivalent tree for this call.
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you forgot the "params" keyword
public T ExecuteMethod(params object[] parameterValues)
{
//get the number of parameters _method has;
var methodCallExpression = _method.Body as MethodCallExpression;
var arguments = methodCallExpression.Arguments;
var newArguments = new List<Expression>();
for (int i = 0; i < arguments.Count(); i++ )
{
newArguments.Add(Expression.Constant(parameterValues[i]));
}
//"Clone" the expression, specifying the new parameters instead of the old.
var newMethodExpression = Expression.Call(methodCallExpression.Object,
methodCallExpression.Method,
newArguments)
return newMethodExpression.Compile()();
}
}
...
public void InitAndTest()
{
SetExecutableMethod( () => _service.SomeMethod1("param1 placeholder", "param2 placeholder") );
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}
This will work as long as the expression tree can find the Func referred to by MethodCallExpression.method within the current instance.
However, I think there's a much simpler way:
public class FuncManipulator<T>
{
private Func<T> _method;
public void SetExecutableMethod(Func<T> methodParam)
{
_method = methodParam;
}
//you must pass the actual array; we are creating a closure reference that will live
//as long as the delegate
public void SetMethodParams(object[] param)
{
_param = param;
}
public T ExecuteMethod(params object[] passedParam)
{
//We have to re-initialize _param based on passedParam
//instead of simply reassigning the reference, because the lambda
//requires we don't change the reference.
for(int i=0; i<_param.Length; i++)
_param[i] = passedParam.Length <= i ? null : passedParam[i];
//notice we don't pass _param; the lambda already knows about it
//via the reference set up when declaring the lambda.
return _method();
}
}
...
public void InitAndTest()
{
//this is an "external closure" we must keep in memory
object[] param = new object[2];
SetExecutableMethod( () => _service.SomeMethod1(param[0], param[1]) );
//We do so by passing the reference to our object
SetMethodParams(param);
//now, don't ever reassign the entire array.
//the ExecuteMethod function will replace indices without redefining the array.
T result1 = ExecuteMethod("Test1", "Test2");
T result2 = ExecuteMethod("Test3", "Test4");
T result3 = ExecuteMethod("Test6", "Test5");
}

Passing a Function (with parameters) as a parameter?

I want to create a generic to which I can pass a function as a parameter, however this function may include parameters itself so...
int foo = GetCachedValue("LastFoo", methodToGetFoo)
Such that:
protected int methodToGetFoo(DateTime today)
{ return 2; // example only }
Essentially I want to have a method that will check the cache for a value, otherwise will generate the value based on the passed in method.
Thoughts?
It sounds like you want a Func<T>:
T GetCachedValue<T>(string key, Func<T> method) {
T value;
if(!cache.TryGetValue(key, out value)) {
value = method();
cache[key] = value;
}
return value;
}
The caller can then wrap this in many ways; for simple functions:
int i = GetCachedValue("Foo", GetNextValue);
...
int GetNextValue() {...}
or where arguments are involved, a closure:
var bar = ...
int i = GetCachedValue("Foo", () => GetNextValue(bar));
Use System.Action and a lambda expression (anonymous method). For example:
public void myMethod(int integer) {
// Do something
}
public void passFunction(System.Action methodWithParameters) {
// Invoke
methodWithParameters();
}
// ...
// Pass anonymous method using lambda expression
passFunction(() => myMethod(1234));
You can create your own delegate, but in C# 3.0 you may find it more convenient to use the built-in Func<T> delegate family to solve this problem. Example:
public int GetCachedValue(string p1, int p2,
Func<DateTime, int> getCachedValue)
{
// do some stuff in here
// you can call getCachedValue like any normal function from within here
}
This method will take three arguments: a string, an int, and a function that takes a DateTime and returns an int. For example:
int foo = GetCachedValue("blah", 5, methodToGetFoo); // using your method
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda
Different Func<T, U, V...> etc. types exist in the framework to accommodate methods with different amounts of arguments.
Create a delegate for the method methodToGetFoo
public delegate object GenerateValue(params p);
public event GenerateValue OnGenerateValue;
Define GetCachedValue to use the delegate
int GetCachedValue(string key, GenerateValue functionToCall);
Then in the implementation of OnGenerateValue you can check the param's.
Here is something simple I started that can be taken a bit further (as I did for a commercial project).
In my case this was to cache web service calls, and was used something like:
WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1)); // x is the ws instance

Categories

Resources