假设我有以下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但是我不必在每次通话后总是打开/关闭客户端。
答案 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();
}
}
结果是:
答案 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
类型,并采用T1
和T2
类型的两个参数。
第二行定义了一个返回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.