如何将多个方法(带参数)作为参数传递?

时间:2022-12-07 04:06:40

Suppose I have the following WCF code:

假设我有以下WCF代码:

  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.

而且由于我注意到try ... catch和其他逻辑是重复的,更不用说设置WCF调用是昂贵的,我想向这个函数发送许多“方法和参数”。

In essence pass GetData(2) and GetData("data") as a method array, and have the results return either asynchronously or synchronously.

实质上将GetData(2)和GetData(“data”)作为方法数组传递,并使结果异步或同步返回。

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.

我想我可以有两个'ref'对象来处理结果[]和对结果[]的共享锁。但是我不确定如何将“带参数的方法”作为参数传递给另一个函数。

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.

我问这个问题所以我可以优化这种方法来处理WCF异常和重试,但所以我不必总是在每次调用后打开/关闭客户端。

6 个解决方案

#1


7  

Use delegates and pass them in a list.

使用委托并在列表中传递它们。

The C# Func<T> delegate is used when a return value is needed.

当需要返回值时,使用C#Func 委托。

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.

这只是一个例子;如果你的方法没有返回任何东西,你可以使用C#Action委托,它只执行一个动作而不返回任何值。

List<Action> actionList = new List<Action>();actionList.Add( () => ProcessData("data")); // ProcessData is a void with no return typeactionList.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:

如何将多个方法(带参数)作为参数传递?

#2


1  

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.

我不会在这里使用委托,因为那时你受到类型的约束,并解决它变得可怕和过于复杂。我只需要一个回调,一旦设置好就可以让你*统治ServiceClient。我认为这是一个有名字但我不知道的模式。

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:

DoSpecificStuff是一个实现接口的类,允许您使用代理进行特定调用:

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.

所以你有很多实现接口的类,它们都“共享”同一个地方的try-catch样板代理。

#3


1  

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.

Bellow是一个如何创建委托集合及其参数的示例,然后在不知道方法定义的情况下稍后调用它们。据我所知,如果你想在一个通用调用中调用具有不同定义的方法,你必须做这样的事情。

   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);   }

#4


0  

You could use C# delegates:

您可以使用C#委托:

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:

委托是一种类型,表示对具有特定参数列表和返回类型的方法的引用。实例化委托时,可以将其实例与具有兼容签名和返回类型的任何方法相关联。您可以通过委托实例调用(或调用)该方法。委托用于将方法作为参数传递给其他方法。事件处理程序只不过是通过委托调用的方法。您可以创建自定义方法,并且诸如Windows控件之类的类可以在发生特定事件时调用您的方法。以下示例显示了委托声明:

More on this:http://msdn.microsoft.com/en-us/library/ms173171.aspx

更多相关信息:http://msdn.microsoft.com/en-us/library/ms173171.aspx

#5


0  

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.

第一行声明函数strategy()接受函数f;该函数返回类型R并采用类型T1和T2的两个参数。

The second line defines a function that returns a bool and accepts two string.

第二行定义了一个返回bool并接受两个字符串的函数。

The third line invokes the strategy passing it the predicate as a parameter.

第三行调用策略将谓词作为参数传递给它。

#6


0  

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:

不确定要了解您要实现的目标,但基本上如果您的服务公开GetData(int)方法和GetData(字符串)方法以及异步代理,您应该使用以下内容异步调用它们:

var getData = proxy.GetDataAsync(2);var getData2 = proxy.GetDataAsync("data");await Task.WhenAll(getData, getData2);// Gets the result using getData.Result...etc.

#1


7  

Use delegates and pass them in a list.

使用委托并在列表中传递它们。

The C# Func<T> delegate is used when a return value is needed.

当需要返回值时,使用C#Func 委托。

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.

这只是一个例子;如果你的方法没有返回任何东西,你可以使用C#Action委托,它只执行一个动作而不返回任何值。

List<Action> actionList = new List<Action>();actionList.Add( () => ProcessData("data")); // ProcessData is a void with no return typeactionList.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:

如何将多个方法(带参数)作为参数传递?

#2


1  

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.

我不会在这里使用委托,因为那时你受到类型的约束,并解决它变得可怕和过于复杂。我只需要一个回调,一旦设置好就可以让你*统治ServiceClient。我认为这是一个有名字但我不知道的模式。

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:

DoSpecificStuff是一个实现接口的类,允许您使用代理进行特定调用:

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.

所以你有很多实现接口的类,它们都“共享”同一个地方的try-catch样板代理。

#3


1  

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.

Bellow是一个如何创建委托集合及其参数的示例,然后在不知道方法定义的情况下稍后调用它们。据我所知,如果你想在一个通用调用中调用具有不同定义的方法,你必须做这样的事情。

   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);   }

#4


0  

You could use C# delegates:

您可以使用C#委托:

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:

委托是一种类型,表示对具有特定参数列表和返回类型的方法的引用。实例化委托时,可以将其实例与具有兼容签名和返回类型的任何方法相关联。您可以通过委托实例调用(或调用)该方法。委托用于将方法作为参数传递给其他方法。事件处理程序只不过是通过委托调用的方法。您可以创建自定义方法,并且诸如Windows控件之类的类可以在发生特定事件时调用您的方法。以下示例显示了委托声明:

More on this:http://msdn.microsoft.com/en-us/library/ms173171.aspx

更多相关信息:http://msdn.microsoft.com/en-us/library/ms173171.aspx

#5


0  

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.

第一行声明函数strategy()接受函数f;该函数返回类型R并采用类型T1和T2的两个参数。

The second line defines a function that returns a bool and accepts two string.

第二行定义了一个返回bool并接受两个字符串的函数。

The third line invokes the strategy passing it the predicate as a parameter.

第三行调用策略将谓词作为参数传递给它。

#6


0  

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:

不确定要了解您要实现的目标,但基本上如果您的服务公开GetData(int)方法和GetData(字符串)方法以及异步代理,您应该使用以下内容异步调用它们:

var getData = proxy.GetDataAsync(2);var getData2 = proxy.GetDataAsync("data");await Task.WhenAll(getData, getData2);// Gets the result using getData.Result...etc.