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

时间:2014-01-28 17:55:01

标签: c# performance wcf delegates closures

假设我有以下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      
  }

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

本质上将GetData(2)GetData("data")作为方法数组传递,并使结果以异步或同步方式返回。

我将如何做到这一点?

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

也许另一种看待这种情况的方法可能是一个函数指针数组,使用不同的参数进行相同的函数。

有人能推动我做正确的方法吗?

更多信息:

我问这个问题so I can optimize this approach to handling WCF exceptions and retries但是我不必在每次通话后总是打开/关闭客户端。

6 个答案:

答案 0 :(得分:7)

使用委托并将其传递到列表中。

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

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

(只要返回类型相同,这将有效)

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

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

回应一些意见:

此代码编译并完全等效:

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

结果是:

enter image description here

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我不会在这里使用委托,因为那时你受类型约束并解决它变得可怕和过于复杂。我只需要一个回调,一旦设置完成就可以让你自由统治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      
    }
}

然后你调用方法如:

MyMethod(new DoSpecificStuff());

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

class DoSpecificStuff : IProxyActionCallback
{
    public void DoProxyStuff(ServiceClient proxy)
    {
        proxy.GetData(2);
        if (proxy.State = CommunicationState.Opened)
        {
            proxy.GetData("data");
        }
    }
}

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

答案 3 :(得分:0)

您可以使用C#委托:

  

委托是一种表示带有a的方法的引用的类型   特定参数列表和返回类型。当你实例化一个   委托,您可以将其实例与任何方法关联   兼容的签名和返回类型。你可以调用(或调用)   通过委托实例的方法。代表们习惯了   方法作为其他方法的参数。事件处理程序仅此而已   而不是通过委托调用的方法。您创建一个自定义   方法,以及诸如Windows控件之类的类可以调用您的方法   当某个事件发生时。以下示例显示了一个委托   声明:

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

答案 4 :(得分:0)

您可以通过以下方式传递函数:

public void strategy<R, T1, T2>(Func<R, T1, T2> f);

public bool predicate(string a, string b);

strategy<bool, string, string>(predicate);

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

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

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

答案 5 :(得分:0)

不确定要了解您要实现的目标,但基本上如果您的服务公开GetData(int)方法和GetData(string)方法以及异步代理,您应该使用某些东西异步调用像:

var getData = proxy.GetDataAsync(2);
var getData2 = proxy.GetDataAsync("data");

await Task.WhenAll(getData, getData2);

// Gets the result using getData.Result...etc.