【问题标题】:Delegates, lambdas and Func代表、lambda 和 Func
【发布时间】:2014-10-22 22:33:15
【问题描述】:

我有一个案例,我需要调用几个不同的 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 <== //
}

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

【问题讨论】:

    标签: c#-4.0 lambda delegates


    【解决方案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;
        };
    }
    

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

    上面的代码应该可以为你工作,但它确实不是编写代码的正确方法。

    我假设SetupCleanUp 代码都是关于实例化您正在调用的_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;
        };
    }
    

    理想情况下,如果您将SetupCleanUp 代码带入Execute 方法,这样调用设置和清理代码的唯一方法就是通过Execute 方法。

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

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

    如果我遗漏了什么,请告诉我。

    【讨论】:

      【解决方案2】:

      替换:

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

      【讨论】:

      • 我注意到有人对此表示反对。原始解决方案是否有问题,还是纯粹为了格式化而投反对票?如果纯粹是为了格式化,我希望这不是 StackOverflow 用户的常见做法。
      • 当我发布这个问题时,它在几秒钟内就被否决了。我在发布后刷新了页面,瞧——投了反对票。不知道发生了什么!
      • 您的更改有效,除非我逐步执行 Execute 方法。出于某种原因,| resp = executeThisAction; |部分实际上并未执行。它永远不会命中传入的目标方法。
      • 没关系 - 我对返回变量的内部定义有误。现在像冠军一样工作!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多