Pass another class method as parameter [duplicate] - 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

Invoke Function with async method delegate in C# [duplicate]

I have several methods all with the same parameter types and return values but different names and blocks. I want to pass the name of the method to run to another method that will invoke the passed method.
public int Method1(string)
{
// Do something
return myInt;
}
public int Method2(string)
{
// Do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
// Do stuff
int i = myMethodName("My String");
// Do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
This code does not work but this is what I am trying to do. What I don't understand is how to write the RunTheMethod code since I need to define the parameter.
You can use the Func delegate in .NET 3.5 as the parameter in your RunTheMethod method. The Func delegate allows you to specify a method that takes a number of parameters of a specific type and returns a single argument of a specific type. Here is an example that should work:
public class Class1
{
public int Method1(string input)
{
//... do something
return 0;
}
public int Method2(string input)
{
//... do something different
return 1;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
You need to use a delegate. In this case all your methods take a string parameter and return an int - this is most simply represented by the Func<string, int> delegate1. So your code can become correct with as simple a change as this:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Delegates have a lot more power than this, admittedly. For example, with C# you can create a delegate from a lambda expression, so you could invoke your method this way:
RunTheMethod(x => x.Length);
That will create an anonymous function like this:
// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
return x.Length;
}
and then pass that delegate to the RunTheMethod method.
You can use delegates for event subscriptions, asynchronous execution, callbacks - all kinds of things. It's well worth reading up on them, particularly if you want to use LINQ. I have an article which is mostly about the differences between delegates and events, but you may find it useful anyway.
1 This is just based on the generic Func<T, TResult> delegate type in the framework; you could easily declare your own:
public delegate int MyDelegateType(string value)
and then make the parameter be of type MyDelegateType instead.
From OP's example:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
You can try Action Delegate! And then call your method using
public bool RunTheMethod(Action myMethodName)
{
myMethodName(); // note: the return value got discarded
return true;
}
RunTheMethod(() => Method1("MyString1"));
Or
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Then simply call method
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
In order to provide a clear and complete answer, I'm going to start from the very beginning before showing three possible solutions.
A brief introduction
All .NET languages (such as C#, F#, and Visual Basic) run on top of the Common Language Runtime (CLR), which is a VM that runs code in the Common Intermediate Language (CIL), which is way higher level than machine code. It follows that methods aren't Assembly subroutines, nor are they values, unlike functional languages and JavaScript; rather, they're symbols that CLR recognizes. Not being values, they cannot be passed as a parameter. That's why there's a special tool in .NET. That is, delegates.
What's a delegate?
A delegate represents a handle to a method (the term handle is to be preferred over pointer as the latter would be an implementation detail). Since a method is not a value, there has to be a special class in .NET, namely Delegate, which wraps up any method. What makes it special is that, like very few classes, it needs to be implemented by the CLR itself and couldn't be simply written as a class in a .NET language.
Three different solutions, the same underlying concept
The type–unsafe way
Using the Delegate special class directly.
Example:
static void MyMethod()
{
Console.WriteLine("I was called by the Delegate special class!");
}
static void CallAnyMethod(Delegate yourMethod)
{
yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}
static void Main()
{
CallAnyMethod(MyMethod);
}
The drawback here is your code being type–unsafe, allowing arguments to be passed dynamically, with no constraints.
The custom way
Besides the Delegate special class, the concept of delegates spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are type–checked the same way as “normal” method invocations, making for type-safe code.
Example:
delegate void PrintDelegate(string prompt);
static void PrintSomewhere(PrintDelegate print, string prompt)
{
print(prompt);
}
static void PrintOnConsole(string prompt)
{
Console.WriteLine(prompt);
}
static void PrintOnScreen(string prompt)
{
MessageBox.Show(prompt);
}
static void Main()
{
PrintSomewhere(PrintOnConsole, "Press a key to get a message");
Console.Read();
PrintSomewhere(PrintOnScreen, "Hello world");
}
The standard library's way
Alternatively, you can stick with a delegate that's part of the .NET Standard:
Action wraps up a parameterless void method;
Action<T1> wraps up a void method with one parameter of type T1;
Action<T1, T2> wraps up a void method with two parameters of types T1 and T2, respectively,
and so forth;
Func<TR> wraps up a parameterless function with TR return type;
Func<T1, TR> wraps up a function with TR return type and with one parameter of type T1;
Func<T1, T2, TR> wraps up a function with TR return type and with two parameters of types T1 and T2, respectively;
and so forth.
However, bear in mind that by using predefined delegates like these, parameter names won't be self-describing, nor is the name of the delegate type meaningful as to what instances are supposed to do. Therefore, refrain from using them in contexts where their purpose is not absolutely self-evident.
The latter solution is the one most people posted. I'm also mentioning it in my answer for the sake of completeness.
The solution involves Delegates, which are used to store methods to call. Define a method taking a delegate as an argument,
public static T Runner<T>(Func<T> funcToRun)
{
// Do stuff before running function as normal
return funcToRun();
}
Then pass the delegate on the call site:
var returnValue = Runner(() => GetUser(99));
You should use a Func<string, int> delegate, that represents a function taking a string argument and returning an int value:
public bool RunTheMethod(Func<string, int> myMethod)
{
// Do stuff
myMethod.Invoke("My String");
// Do stuff
return true;
}
Then invoke it this way:
public bool Test()
{
return RunTheMethod(Method1);
}
While the accepted answer is absolutely correct, I would like to provide an additional method.
I ended up here after doing my own searching for a solution to a similar question.
I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!
So the solution, as simple as it sounds once you realize it, eluded me until now.
Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.
Here is an example Which can help you better to understand how to pass a function as a parameter.
Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.
Here you need to create a delegate.
Parent.cs
// declaration of delegates
public delegate void FillName(String FirstName);
Now create a function which will fill your textbox and function should map delegates
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Now on button click you need to open a Child popup window.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page
ChildPopUp.cs
public Parent.FillName obj;
public PopUp(Parent.FillName objTMP)//parameter as deligate type
{
obj = objTMP;
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
obj(txtFirstName.Text);
// Getname() function will call automatically here
this.DialogResult = true;
}
If you want to pass Method as parameter, use:
using System;
public void Method1()
{
CallingMethod(CalledMethod);
}
public void CallingMethod(Action method)
{
method(); // This will call the method that has been passed as parameter
}
public void CalledMethod()
{
Console.WriteLine("This method is called by passing it as a parameter");
}
If the method passed needs to take one argument and return a value, Func is the best way to go. Here is an example.
public int Method1(string)
{
// Do something
return 6;
}
public int Method2(string)
{
// Do something different
return 5;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
// Do stuff
int i = myMethodName("My String");
Console.WriteLine(i); // This is just in place of the "Do more stuff"
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Read the docs here
However, if your method that is passed as a parameter does not return anything, you can also use Action. It supports up to 16 paramaters for the passed method. Here is an example.
public int MethodToBeCalled(string name, int age)
{
Console.WriteLine(name + "'s age is" + age);
}
public bool RunTheMethod(Action<string, int> myMethodName)
{
// Do stuff
myMethodName("bob", 32); // Expected output: "bob's age is 32"
return true;
}
public bool Test()
{
return RunTheMethod(MethodToBeCalled);
}
Read the documentation here
Here is an example without a parameter:
http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
with params:
http://www.daniweb.com/forums/thread98148.html#
you basically pass in an array of objects along with name of method. you then use both with the Invoke method.
params Object[] parameters
class PersonDB
{
string[] list = { "John", "Sam", "Dave" };
public void Process(ProcessPersonDelegate f)
{
foreach(string s in list) f(s);
}
}
The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.
class Client
{
static void Main()
{
PersonDB p = new PersonDB();
p.Process(PrintName);
}
static void PrintName(string name)
{
System.Console.WriteLine(name);
}
}
I don't know who might need this, but in case you're unsure how to send a lambda with a delegate, when the function using the delegate doesn't need to insert any params in there you just need the return value.
SO you can also do this:
public int DoStuff(string stuff)
{
Console.WriteLine(stuff);
}
public static bool MethodWithDelegate(Func<int> delegate)
{
///do stuff
int i = delegate();
return i!=0;
}
public static void Main(String[] args)
{
var answer = MethodWithDelegate(()=> DoStuff("On This random string that the MethodWithDelegate doesn't know about."));
}

Action calling a static method with an argument, without capturing this in C#

I want to store a method call in an action. That method is a static method, but with a string argument that varies. So I want to store "call StaticMethod with argument "myString" in an Action.
But... without capturing this.
I can store an anonymous method () => StaticMethod(myString) in the action , but this captures the action target (this). (Edit: it doesn't. See the accepted answer).
I can store the static method in the action, but then I'm missing the argument.
I could store the static method and the arguments separately, but due to technical reasons, this is cumbersome and ugly.
Do I have any other possibility?
[Edit]
In other words, I want to do this:
private void MyMethod(string myString){
var action = Call StaticMethod with argument myString.
}
And somewhere else, where I have access to action, but don't know anything about the string, or that there are arguments:
action.Invoke();
action can capture the string, but can't capture this (the call target of MyMethod).
Given the following assumptions:
myString is a local variable, or a parameter to the method (Not! a property or field)
StaticMethod is really a static method
There are no other delegates being constructed in the same method as you want to construct action
then the following:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
}
public static void StaticMethod(string value) { }
will be compiled as this:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
internal void <M>b__0()
{
StaticMethod(myString);
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
}
As you can see, your lambda is lifted out to a generated display class, and myString is also lifted out from your method, going from a local variable to a field on that display class. This is the closure, and the object constructed in the M method will be the target of the action, and this closure will not capture this.
You can see this in action here: SharpLab
Note that small changes to your code will invalidate this as the assumptions change. For instance, if you also, in the same method, declare another delegate that also requires a closure and also requires access to this, then the same closure will be shared between the two delegates.
Example:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
Action otherAction = () => StaticMethod(Property);
}
public string Property => "Value";
Generates this code:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
public C <>4__this;
internal void <M>b__0()
{
StaticMethod(myString);
}
internal void <M>b__1()
{
StaticMethod(<>4__this.Property);
}
}
public string Property
{
get
{
return "Value";
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.<>4__this = this;
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
Action action2 = new Action(<>c__DisplayClass0_.<M>b__1);
}
As you can see, the same closure is used to support both delegates, and now both delegates has a reference to a closure that captures this.
If you can't define your action at call site at compile time e.:
Action a = () => StaticMethod("myString");
Then you will probably want to use expressions for this.
Example Code:
[Fact]
public void SampleActionWithoutThisScopeTests()
{
// Using Compile Time Action
Action compileTimeAction = () => MyStaticMethod("CompileTime myString");
compileTimeAction.Invoke();
// Using Compiled Expression
var myString = "Expression myString";
var methodInfo = this.GetType().GetMethod(nameof(MyStaticMethod), BindingFlags.Static | BindingFlags.Public);
var stringArgumentConstant = Expression.Constant(myString);
var callExpression = Expression.Call(null, methodInfo, stringArgumentConstant);
var lambda = Expression.Lambda<Action>(callExpression);
var action = lambda.Compile();
action.Invoke();
}
public static void MyStaticMethod(string input)
{
Console.WriteLine(input);
}
EDIT
If you can, and meet the requirements for the compiler-generated closure to not contain "this" via normal lambda syntax (see #Lasse V. Karlsen answer, then definitely use that approach!

How to create a dynamic delegate object by type in C#?

Let's say I have a type, which I know to be derived from a Delegate type. I would like to create an object of this type wrapping an anonymous delegate that accepts arbitrary params and returns an object of correct return type:
var retType = type.GetMethod("Invoke").ReturnType;
var obj = Delegate.CreateDelegate(type, delegate(object[] args) {
...
if (retType != typeof(void))
... somehow create object of type retType and return it ...
});
Obviously this won't compile, because CreateDelegate expects a MethodInfo as the second argument. How can I do this correctly?
Update: A little more info on what I am trying to achieve. There are two applications running - client in a browser and a server in C#. Browser is able to call remote functions on the server side by serializing arguments to JSON and sending the call over the network (like in RPC). This works already, but I would like to add support for callbacks. For example:
JavaScript (client):
function onNewObject(uuid) { console.log(uuid); }
server.notifyAboutNewObjects(onNewObject);
C# (server):
void notifyAboutNewObjects(Action<string> callback) {
...
callback("new-object-uuid");
...
}
The middleware code will receive a call from the browser and will need to generate fake callback delegate that will actually send the call to callback back to the browser and block the thread until it completes. The code for sending/receiving is there already, I am just stuck on how to generate a generic delegate that will simply put all arguments into an array and pass them to the sending code.
Update: If someone can write code that will generate such a delegate at runtime (e.g. using DynamicMethod) , I'll consider that a valid answer. I just don't have enough time to learn how to do this and hope that someone experienced will be able to write this code quickly enough. Essentially the code should just take arbitrary delegate params (list and types are available at runtime), put them into an array and call generic method. The generic method will always return an object, which should be cast into respective return type or ignored if the function returns void.
Uppdate: I've created a small test program that demonstrates what I need:
using System;
using System.Reflection;
namespace TestDynamicDelegates
{
class MainClass
{
// Test function, for which we need to create default parameters.
private static string Foobar(float x, Action<int> a1, Func<string, string> a2) {
a1(42);
return a2("test");
}
// Delegate to represent generic function.
private delegate object AnyFunc(params object[] args);
// Construct a set of default parameters to be passed into a function.
private static object[] ConstructParams(ParameterInfo[] paramInfos)
{
object[] methodParams = new object[paramInfos.Length];
for (var i = 0; i < paramInfos.Length; i++) {
ParameterInfo paramInfo = paramInfos[i];
if (typeof(Delegate).IsAssignableFrom(paramInfo.ParameterType)) {
// For delegate types we create a delegate that maps onto a generic function.
Type retType = paramInfo.ParameterType.GetMethod("Invoke").ReturnType;
// Generic function that will simply print arguments and create default return value (or return null
// if return type is void).
AnyFunc tmpObj = delegate(object[] args) {
Console.WriteLine("Invoked dynamic delegate with following parameters:");
for (var j = 0; j < args.Length; j++)
Console.WriteLine(" {0}: {1}", j, args[j]);
if (retType != typeof(void))
return Activator.CreateInstance(retType);
return null;
};
// Convert generic function to the required delegate type.
methodParams[i] = /* somehow cast tmpObj into paramInfo.ParameterType */
} else {
// For all other argument type we create a default value.
methodParams[i] = Activator.CreateInstance(paramInfo.ParameterType);
}
}
return methodParams;
}
public static void Main(string[] args)
{
Delegate d = (Func<float, Action<int>,Func<string,string>,string>)Foobar;
ParameterInfo[] paramInfo = d.Method.GetParameters();
object[] methodParams = ConstructParams(paramInfo);
Console.WriteLine("{0} returned: {1}", d.Method.Name, d.DynamicInvoke(methodParams));
}
}
}
I wrote a opensource PCL library, called Dynamitey (in nuget), that does all sorts of dynamic things using the C# DLR. .
It specifically has a static method called Dynamic.CoerceToDelegate(object invokeableObject, Type delegateType) That basically wraps the dynamic invocation of a DynamicObject or a more general delegate, with the specific Type of delegate using CompiledExpressions (source).
using System.Dynamic you can create an invokable object:
public class AnyInvokeObject:DynamicObject{
Func<object[],object> _func;
public AnyInvokeObject(Func<object[],object> func){
_func = func;
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result){
result = _func(args);
return true;
}
}
Then in your sample:
var tmpObj = new AnyInvokeObject(args => {
Console.WriteLine("Invoked dynamic delegate with following parameters:");
for (var j = 0; j < args.Length; j++)
Console.WriteLine(" {0}: {1}", j, args[j]);
if (retType != typeof(void))
return Activator.CreateInstance(retType);
return null;
});
methodParams[i] = Dynamic.CoerceToDelegate(tmpObj, paramInfo.ParameterType);
You could either check out the source code for SignalR or simply just use it.
Register a function in browser that the server can call
var connection = $.hubConnection();
var yourHubProxy = connection.createHubProxy('yourHub');
yourHubProxy.on('addMessageToConsole', function (message) {
console.log(message);
});
and on the server
public class YourHub : Hub
{
public void SendMessage(string message)
{
Clients.All.addMessageToConsole(message);
}
}
See here for more examples.
How about a solution without delegates?
(warning: rampant pseudocode)
class AbstractServerToClientMessage {
public virtual string ToJSON();
}
class OnNewObjectMessage: AbstractServerToClientMessage {...}
class OnSomethingElseHappenedMessage: AbstractServerToClientMessage {...}
void NotifyClient(AbstractServerToClientMessage message)
event OnNewObject;
event OnSomethingElseHappened;
void notifyAboutNewObjects() {
...
OnNewObject += NotifyClient;
...
}
void AddNewObject(SomeObject obj) {
OnNewObjectMessage message(obj);
OnNewObject(message);
// actually add the object
}
messages will be serialized anyway, so why bother? Polymorphism will take care of the rest. The only requirement is to have a set of messages which correspond to each event type.
Returning the value may be implemented by writing to some field in the AbstractServerToClientMessage.
Or, you can actually have a delegate with a fixed signature accepting a similar AbstractServerToClientMessage. Again, polymorphism (+ a class factory for deserialization) will allow to cast it to correct type of message.

Wrap multiple method calls (that each have different signatures) in a single handler

I have multiple calls to methods in a 3rd party library.
These methods have a wide variety of different signatures / parameter combinations.
There are specific errors that the 3rd party library generates that I would like to catch and handle, and since the resolution is the same I would like it to take place in a single handler.
So I want to be able to have a method that essentially takes in as parameters a function (delegate) and its arguments, and invokes it inside some try/catch logic.
I don't know if its just not possible or I'm not getting the syntax right, but I can't figure out how to handle the fact that the signature for each method being passed in is different.
Any suggestions?
You could use Action and Func<T> to wrap the methods, and closures to pass arguments.
public TResult CallMethod<TResult>(Func<ThirdPartyClass, TResult> func)
{
try
{
return func(this.wrappedObject);
}
catch(ThirdPartyException e)
{
// Handle
}
}
public void CallMethod(Action<ThirdPartyClass> method)
{
this.CallMethod(() => { method(this.WrappedObject); return 0; });
}
You could then use this via:
var result = wrapper.CallMethod(thirdParty => thirdParty.Foo(bar, baz));
Edit: The above was assuming you were wrapping an instance of the third party library. Given (from your comments) that these are static methods, you can just use:
public static TResult CallMethod<TResult>(Func<TResult> func)
{
try
{
return func();
}
catch(ThirdPartyException e)
{
// Handle
}
}
public static void CallMethod(Action method)
{
CallMethod(() => { method(); return 0; });
}
And then call via:
var result = Wrapper.CallMethod(() => ThirdParty.Foo(bar, baz));

Callbacks in C#

I want to have a library that will have a function in it that accepts an object for it's parameter.
With this object I want to be able to call a specified function when X is finished. The function that will be called is to be specified by the caller, and X will be done and monitored by the library.
How can I do this?
For reference I'm using C# and .NET 3.5
Two options for you:
Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.
Use an interface
Using a delegate/lambda
public static void DoWork(Action processAction)
{
// do work
if (processAction != null)
processAction();
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate() { Console.WriteLine("Completed"); });
// using Lambda
DoWork(() => Console.WriteLine("Completed"));
}
If your callback needs to have something passed to it, you can use a type parameter on Action:
public static void DoWork(Action<string> processAction)
{
// do work
if (processAction != null)
processAction("this is the string");
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate(string str) { Console.WriteLine(str); });
// using Lambda
DoWork((str) => Console.WriteLine(str));
}
If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)
More about delegates here.
Using an interface
public interface IObjectWithX
{
void X();
}
public class MyObjectWithX : IObjectWithX
{
public void X()
{
// do something
}
}
public class ActionClass
{
public static void DoWork(IObjectWithX handlerObject)
{
// do work
handlerObject.X();
}
}
public static void Main()
{
var obj = new MyObjectWithX()
ActionClass.DoWork(obj);
}
Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.
The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.
You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.
public delegate void Callback<T>(T state, OperationResult result)
Then:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...>
delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)
The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.
Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.
The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.
You can use System.Action available in C#.NET for callback functions. Please check this sample example:
//Say you are calling some FUNC1 that has the tight while loop and you need to
//get updates on what percentage the updates have been done.
private void ExecuteUpdates()
{
Func1(Info => { lblUpdInfo.Text = Info; });
}
//Now Func1 would keep calling back the Action specified in the argument
//This System.Action can be returned for any type by passing the Type as the template.
//This example is returning string.
private void Func1(System.Action<string> UpdateInfo)
{
int nCount = 0;
while (nCount < 100)
{
nCount++;
if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString());
//System.Threading.Thread.Sleep(1000);
}
}

Categories