代表,lambdas和Func

时间:2014-10-22 22:33:15

标签: c#-4.0 lambda delegates

我有一个案例,我需要调用几个不同的Web端点,并且需要对每个呼叫进行相同的设置和拆除。我正在尝试编写一个更通用的方法,我可以将我想要执行的方法与包一起传递给端点并期望返回一个字符串。


我可以通过我的代码拨打电话:

var ret = WebServiceHandler.Execute(WebServiceHandler.LoadNewAsset(package));

Execute的定义如下:

internal static string Execute<T>(Func<T, string> executeThisAction)
{
    Func<T, string> resp;

    Setup();
    resp = executeThisAction;
    CleanUp();

    return resp.ToString();
}

这是我想要执行的方法之一:

internal static Func<CarsWS_AssetLoad, string> LoadNewAsset(AssetLoad package)
{
    string resp;
    try
    {
        // Make the web service call...
        var assetLoadReturn = _service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});

        // Evaluate results...
        if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
            resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
                ? "Got assetID: " + result.asset.assetID
                : "No assetID returned.";
        else
            resp = result.responseDescription.Trim();
    }
    catch (Exception ex)
    {
        resp = "Error calling LoadNewAsset()." + Environment.NewLine + ex.GetFullMessage();
    }

    return resp;  // <== THIS IS NOT A VALID RETURN <== //
}

此时我的大脑正在关闭。如何正确地将字符串返回到调用堆栈???

2 个答案:

答案 0 :(得分:1)

我认为在LoadNewAsset方法中,CarsWS_AssetLoad类实际上与AssetLoad相同,这只是您问题的编辑问题。

在这种情况下,我认为这就是你想要的:

internal static string Execute<T>(Func<T, string> executeThisAction, AssetLoad package)
{
    string resp;

    Setup();
    resp = executeThisAction(package);
    CleanUp();

    return resp;
}

internal static Func<AssetLoad, string> LoadNewAsset()
{
    return package =>
    {
        string resp;

        var assetLoadReturn = _service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});

        if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
            resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
                ? "Got assetID: " + result.asset.assetID
                : "No assetID returned.";
        else
            resp = result.responseDescription.Trim();

        return resp;
    };
}

result中使用变量LoadNewAsset也有点令人困惑。您的意思是使用LoadNewAsset吗?

上面的代码应该可以为你工作,但这不是正确的编码方式。

我认为Setup&amp; CleanUp代码是关于实例化您正在调用的_service吗?

所以关键是用这种方式编码:

internal static string Execute<T>(Func<IAssetService, T, string> serviceCall, AssetLoad package)
{
    string resp;

    var service = Setup();
    resp = serviceCall(service, package);
    CleanUp(service);

    return resp;
}

internal static Func<IAssetService, AssetLoad, string> GetLoadNewAssetFunc()
{
    return (service, package) =>
    {
        string resp;

        var assetLoadReturn = service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});

        if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
            resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
                ? "Got assetID: " + result.asset.assetID
                : "No assetID returned.";
        else
            resp = result.responseDescription.Trim();

        return resp;
    };
}

理想情况下,如果你带上Setup&amp; CleanUp方法中的Execute代码,因此调用设置和清理代码的唯一方法是通过Execute方法。

更好的是,如果服务类实现IDisposable,那么执行代码将如下所示:

internal static string Execute<T>(Func<IAssetService, T, string> serviceCall, AssetLoad package)
{
    using (var service = Setup())
    {
        return serviceCall(service, package);
    }
}

如果我错过了什么,请告诉我。

答案 1 :(得分:-1)

替换:

internal static string Execute<T>(Func<T, string> executeThisAction)

internal static string Execute<T>(Func<T, string> executeThisAction, T argument)

然后替换:

internal static Func<CarsWS_AssetLoad, string> LoadNewAsset(AssetLoad package)

internal static string LoadNewAsset(AssetLoad package)

然后调用它:

var ret = WebServiceHandler.Execute(WebServiceHandler.LoadNewAsset, package);