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

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.

Related

How to create a dictionary of string and delegate in C# [duplicate]

In regards to the answer for this question Passing DataContext into Action(), how do I return a value from action(db)?
SimpleUsing.DoUsing(db => {
// do whatever with db
});
Should be more like:
MyType myType = SimpleUsing.DoUsing<MyType>(db => {
// do whatever with db. query buit using db returns MyType.
});
You can use Func<T, TResult> generic delegate. (See MSDN)
Func<MyType, ReturnType> func = (db) => { return new MyType(); }
Also there are useful generic delegates which considers a return value:
Converter<TInput, TOutput> (MSDN)
Predicate<TInput> - always return bool (MSDN)
Method:
public MyType SimpleUsing.DoUsing<MyType>(Func<TInput, MyType> myTypeFactory)
Generic delegate:
Func<InputArgumentType, MyType> createInstance = db => return new MyType();
Execute:
MyType myTypeInstance = SimpleUsing.DoUsing(
createInstance(new InputArgumentType()));
OR explicitly:
MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
Your static method should go from:
public static class SimpleUsing
{
public static void DoUsing(Action<MyDataContext> action)
{
using (MyDataContext db = new MyDataContext())
action(db);
}
}
To:
public static class SimpleUsing
{
public static TResult DoUsing<TResult>(Func<MyDataContext, TResult> action)
{
using (MyDataContext db = new MyDataContext())
return action(db);
}
}
This answer grew out of comments so I could provide code. For a complete elaboration, please see #sll's answer below.
Use Func<T> rather than Action<T>.
Action<T> acts like a void method with parameter of type T, while Func<T> works like a function with no parameters and which returns an object of type T.
If you wish to give parameters to your function, use Func<TParameter1, TParameter2, ..., TReturn>.
You can also take advantage of the fact that a lambda or anonymous method can close over variables in its enclosing scope.
MyType result;
SimpleUsing.DoUsing(db =>
{
result = db.SomeQuery(); //whatever returns the MyType result
});
//do something with result
In addition to ssls answer: For a software we call a lot of "micro methods" to query this and that from the local machine. Sometimes exceptions appear (file / folder not existing, etc). In order to not repeat our self over and over with try/catch blocks, we used ssls approach with return values:
private T ExecuteAndCatch<T>(Func<T> action, T defaultReturn)
{
try
{
return action();
}
catch (Exception ex)
{
Log.e("Exception during ExecuteAndCatch", ex);
return defaultReturn;
}
}
Example of mentioned micro-methods:
private Boolean CheckKasperskyInstalled() => System.IO.File.Exists(Environment.ExpandEnvironmentVariables(#"%pf_x86%\Kaspersky Lab\Kaspersky Endpoint Security for Windows\avp.exe"));
private Boolean CheckKasperskyRunning() => System.Diagnostics.Process.GetProcessesByName("avp").Length > 0;
And when using, we no longer have to care if these Methods might throw an exception for whatever reason:
cci = new ComputerComplianceInfo();
cci.KasperskyInstalled = ExecuteAndCatch(() => CheckKasperskyInstalled(), false);
cci.KasperskyRunning = ExecuteAndCatch(() => CheckKasperskyRunning(), false);

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.

One Generic Method To Handle Mutliple Delegate Types

I'm working on a project that allows the Client to call remote functions on the Server for its specific instance. Basically, when the client connects it will get its own instance of a shared class, the Client will then call the server with the name of the method return type, and parameters + their expected types.
The way I'm going about it is creating a Prototypes class, and inside it creating Delegates to represent the Method prototypes that are inside the Server's shared class.
Sub Question: What is the best method to go about this? I'm using Delegates but I'm not a fan of double declarations for what's effectively one prototype. An Interface is about what I want, but I can find a good way to create an instance of it because I'm not sure what the Prototype class will contain.
The way I will handle all this is when the Client connects to the Server, the Client will traverse the Prototypes class and get all Fields, it will then attempt to link all of the Fields inside to one generic method to handle any function that gets called, that function will then get it's declared return type & parameter info etc. and then send it off to the server.
My first thought was to use
params object[] param
However Delegate.CreateDelegate errors out at runtime if I say feed it:
public delegate string TestDelegate(string s1, string s2, string[] s3);
public TestDelegate Test;
However, if I create multiple overloads of the Method that all the delegates are linking back to it works fine ex:
public T handleFunc<T>(object param)
{
Console.WriteLine(param as string);
return default(T);
}
public T handleFunc<T>(object param, object param2)
{
Console.WriteLine(param as string);
return default(T);
}
public T handleFunc<T>(object param, object param2, object param3)
{
Console.WriteLine((param3 as string[])[0]);
return default(T);
}
Here's my current code to link the delegates to the handleFunc method:
private void ValidatePrototypes()
{
var fields = typeof(Prototypes).GetFields();
foreach (FieldInfo field in fields)
{
MethodInfo thisfield = field.FieldType.GetMethods()[0];
ParameterInfo[] pi = thisfield.GetParameters();
var handle = typeof(Client).GetMethod("handleFunc", Array.ConvertAll(pi, s => s.ParameterType));
var lambda = handle.MakeGenericMethod(thisfield.ReturnType);
Delegate del = Delegate.CreateDelegate(field.FieldType, this, lambda);
field.SetValue(Functions, del);
}
Console.WriteLine(Functions.Test("", "", new[] { "Hello" }));
}
I effectively need one method for any possible delegate (or whatever the best variant is) to link to and be able to handle the data from there.
I appreciate any responses.
I think this can be done without creating delegates at runtime:
public interface IService {
string Foo(int x);
}
public class ServerClass : IService {
public string Foo(int x) {
return x.ToString();
}
}
public class ClientStub : IService {
protected ITarget target;
public ClientStub(ITarget target) {
this.target = target;
}
public string Foo(int i) {
return (string)target.Invoke(nameof(Foo), i);
}
}
public interface ITarget {
object Invoke(string methodName, params object[] args);
}
public class RemoteTarget : ITarget {
public object Invoke(string methodName, params object[] args) {
// send params over network and return response
}
}
...
new ClientStub(new RemoteTarget()).Foo();
Using your approach has no benefit over this one. The thing they usually do in frameworks is that they implement ClientStub class at runtime using reflection emit, so you dont have to write it by hand.

Can I get a method attribute from a generic delegate?

I'm sure there's an answer already on the forum somewhere, but I haven't been able to find it so far. As per this example I am using anonymous methods in conjunction with a delegate in order to have different methods with the different parameters but the same return type all work as function parameters:
public delegate TestCaseResult Action();
...
[TestDescription("Test whether the target computer has teaming configured")]
public TestCaseResult TargetHasOneTeam()
{
// do some logic here and return
// TestCaseResult
}
[TestDescription("Test whether the target computer has the named team configured")]
public TestCaseResult TargetHasNamedTeam(string teamName)
{
// do some logic here and return
// TestCaseResult
}
...
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
// I want to get the value of the TestDescription attribute here
}
...
// usage
TestThat(() => TargetHasOneTeam());
TestThat(() => TargetHasNamedTeam("Adapter5"));
As you can see from the example, I'd really like to be able to get the TestDescriptionAttribute attribute from within the TestThat() function. I've already poked through the Action parameter which contains my method but haven't been able to "find" my TargetHasOneTeam() method.
If you change TestThat(() => TargetHasOneTeam()) (you wrapping your delegate into another action) to TestThat(TargetHasOneTeam) and change TestThat like this:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
var attrs = action.GetInvocationList()[0].Method.GetCustomAttributes(true);
// I want to get the value of the TestDescription attribute here
}
will give you what you need.
With expressions:
public static void TestThat(Expression<Func<TestResult>> action)
{
var attrs = ((MethodCallExpression)action.Body).Method.GetCustomAttributes(true);
var result = action.Compile()();
}
In this particular case it's essentially inaccessible. You are creating a lambda which executes the method in question. That lambda eventually results in a new method being generated which is eventually the argument of the Action delegate. That method has no relation to TargetHasOneTeam and is only apparently if you dig through the IL instructions in the body.
You could skip the lambda and do a method group conversion here.
TestThat(TargetHasOneTeam);
Now TargetHasOneTeam is being directly assigned to the delegate instance and would be visible in the Delegate::MethodInfo property.
Note: In general though this is a bad idea for precisely the problem you're encountering. The attributes on the method shouldn't affect it's ability to satisfy the delegate instantiation. I would avoid this type of inspection if possible.
You can get the attribute of any member with Attribute.GetCustomAttribute. First check that the attribute is defined. For example:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
if(System.Attribute.IsDefined(action.Method, typeof(TestDescriptionAttribute)))
{
var attribute = (TestDescriptionAttribute)System.Attribute.GetCustomAttribute(action.Method,
typeof(TestDescriptionAttribute));
Console.WriteLine(attribute.TestDescription);
}
}
See this example on MSDN.
class TestAuthorAttribute
{
static void Test()
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
private static void PrintAuthorInfo(System.Type t)
{
System.Console.WriteLine("Author information for {0}", t);
// Using reflection.
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection.
// Displaying output.
foreach (System.Attribute attr in attrs)
{
if (attr is Author)
{
Author a = (Author)attr;
System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version);
}
}
}

Creating a genericly typed Action<> at runtime

Is it possible to create a generically typed Action at run time based on some specified types? In this particular scenario, the body of the Action will ultimately ignore the argument types, as the typed Action<> will just be a wrapper around a no-argument Action, e.g.
Action original = () => { };
...
Action<TType> wrapper = (arg) => {
original();
}
Or, even:
Action<TTypeA, TTypeB> wrapper = (arg) => {
original();
}
As you can see, the body of the typed Action<> ignores the arguments, and their type, it's just acting as a wrapper.
If you're curious as to why I want create this wrapper in the first place, the 'basic' version is that I am ultimately converting the Action to a Delegate for doing a Delegate.Combine(), which requires identical types. All I am trying to accomplish with the Delegate.Combine() is a basic notification that the delegate was fired.
At this point I will probably re-work my design to avoid these types of shenanigans, but I am still very curious how this might be accomplished.
The closest I could get was the following:
private static TType GetTypedDelegate<TType>(Action onComplete)
where TType : class
{
MethodInfo info = typeof(TType).GetMethod("Invoke");
ParameterInfo[] parameters = info.GetParameters();
object result;
if (parameters.Length == 0)
result = onComplete;
else if (parameters.Length == 1)
result = GetTypedDelegate<TType>(onComplete, parameters[0].ParameterType);
// etc
TType onCompleteCasted = Delegate.CreateDelegate(typeof(TType), result, "Invoke") as TType;
return onCompleteCasted;
}
private static Delegate GetTypedDelegate<TType>(Action onComplete, Type type)
{
// This line isn't useful for me right now, since I can't just create a new
// instance of the action with a parameterless constructor ... but I thought I'd throw it in here in case it was of use
Type actionType = typeof(Action<>).MakeGenericType(new[] { type });
// Do some magic here with the type information
// The following of course does not work,but you get the idea of what I am aiming for
Action<type> wrapper = (arg1) =>
{
onComplete();
};
return wrapper as Delegate;
}
I think that the easiest option is to write a generic method and then invoke it dynamically (using Reflection or possibly even using C# 4 dynamic):
class Helper {
public static Action<TType> Wrap1<TType>(Action arg) {
return (arg) => { original(); }
}
}
Invoking the method using Reflection and using typ1 as the generic type argument could look like this:
var meth = typeof(Helper).GetMethod("Wrap1");
var gmeth = meth.MakeGenericMethod(new[] { typ1 });
var genericAction = gmeth.Invoke(null, new object[] { action });
If you don't want to use reflection you can setup some classes like this.
public class ActionWrapper<TTypeA>
{
protected readonly Action _original;
public ActionWrapper(Action original)
{
_original = original;
}
public Action<TTypeA> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a)
{
_original();
}
}
public class ActionWrapper<TTypeA,TTypeB>:ActionWrapper<TTypeA>
{
public ActionWrapper(Action original) : base(original)
{
}
public new Action<TTypeA, TTypeB> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a,TTypeB b)
{
_original();
}
}

Categories

Resources