将接口方法作为参数传递

2024-04-10

Note: 这很可能是非常C#特定语言问题,与以下无关WCF or web services at all.

有3方ASMXWeb 服务,用于数据检索。我创建了一个名为的通用方法ExecuteCommand()用于针对 Web 服务的每个请求。该方法的目的是处理cookie会话/异常和其他常见逻辑。对于每个请求,应使用新的信道,以简化未使用资源的处理。

问题是要使用ExecuteCommand()方法 - 我必须每次初始化一个通道,以便能够传递要作为参数执行的方法。抱歉,如果听起来太复杂。这是一个用法示例:

string color = "blue";
var channel = _strategyFactory.CreateChannel<CarServiceSoapChannel>();
var cars = WcfHelper.ExecuteCommand(channel, () => channel.GetCars(color));
// channel is null here. Channel was closed/aborted, depending on Exception type.

After ExecuteCommand()叫做 -channel已经被处理掉了。之所以channel对象之所以需要,就是能够提供一个要执行的方法作为参数! IE。() => channel.GetCars()。为了进一步支持这些话,这里是WcfHelper类内部:

public static class WcfHelper
{
    public static Cookie Cookie { get; set; }

    public static T ExecuteCommand<T>(IClientChannel channel, Expression<Func<T>> method)
    {
        T result = default(T);

        try
        {
            // init operation context
            using (new OperationContextScope(channel))
            {
                // set the session cookie to header
                if (Cookie != null) {
                    HttpRequestMessageProperty request = new HttpRequestMessageProperty();
                    request.Headers["Cookie"] = cookie.ToString();
                    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = request;  
                }

                // execute method
                var compiledMethod = method.Compile();
                result = compiledMethod.Invoke();
            }
        }
        // do different logic for FaultException, CommunicationException, TimeoutException
        catch (Exception)
        {
            throw;
        }
        finally
        {
            CloseOrAbortServiceChannel(channel);
            channel = null;
        }

        return result;
    }

    private static void CloseOrAbortServiceChannel(ICommunicationObject communicationObject)
    {
        bool isClosed = false;

        if (communicationObject == null || communicationObject.State == CommunicationState.Closed)
            return;

        try
        {
            if (communicationObject.State != CommunicationState.Faulted)
            {
                communicationObject.Close();
                isClosed = true;
            }
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            if (!isClosed)
                AbortServiceChannel(communicationObject);
        }
    }

    private static void AbortServiceChannel(ICommunicationObject communicationObject)
    {
        try
        {
            communicationObject.Abort();
        }
        catch (Exception)
        {
            throw;
        }
    }
}

所以简短的问题 - 是否可以初始化channel里面的变量ExecuteCommand方法本身,同时可以定义在内部执行哪个方法ExecuteCommand对于给定的频道?

我正在尝试完成这样的事情:

string color = "blue";
var cars = WcfHelper.ExecuteCommand<Car[], CarServiceSoapChannel>(channel => channel.GetCars(color));

or even

string color = "blue";
var cars = WcfHelper.ExecuteCommand<CarServiceSoapChannel>(channel => channel.GetCars(color));

当然,任何其他代码改进建议都是受欢迎的,但不是强制性的。

P.S. ASMX添加为Service reference in Visual Studio。因此,有一些为“CarService”自动生成的实体,例如 -CarServiceSoapChannel界面,CarServiceSoapClient类,当然CarService包含 Web 服务方法的接口。在上面的例子中ChannelFactory用于创建一个通道CarServiceSoapChannel接口,因此,这里是问题名称的来源:Passing an interface method as a parameter。这可能有点误导,但我希望从描述本身可以清楚地看出我想要实现的目标。

更新2018年5月25日我听从了@nvoigt的建议,并达到了我想要的结果:

public static TResult ExecuteCommand<TInterface, TResult>(Func<TInterface, TResult> method)
    where TInterface : IClientChannel
{
    TResult result = default(TResult);
    IClientChannel channel = null;

    try
    {
        channel = StrategyFactory.CreateChannel<TInterface>();

        // init operation context
        using (new OperationContextScope(channel))
        {
            // set the session cookie to header
            if (Cookie != null)
                Cookie.SetCookieForSession();

            // execute method
            result = method((TInterface)channel);
        }
    }
    catch (Exception)
    {
        throw;
    }
    finally
    {
        CloseOrAbortServiceChannel(channel);
        channel = null;
    }

    return result;
}

这已经达到了最初的目的。然而,这种方法有一个问题。为了调用该方法 - 您必须显式指定该方法的返回参数。

也就是说,如果你想调用该方法 - 写这样是不够的:

var result = WcfHelper.ExecuteCommand<CarServiceSoapChannel>(channel => channel.IsBlue())

您必须具体指定返回类型应为boolean

var result = WcfHelper.ExecuteCommand<CarServiceSoapChannel, bool>(channel => channel.IsBlue())

我个人不介意编写额外的代码,因为它仍然比我最初的方法实现有很大的优势,但是,我想知道在新版本中可以改进吗?

例如,当我只有 1 个泛型时TResult方法中的类型 - 返回类型<TResult>可以省略。有了 2 个泛型,情况就不再是这样了。无论如何,谢谢你@nvoigt!


您的方法签名应该是:

public static TResult ExecuteCommand<TInterface>(Func<TInterface, TResult> method)

然后在你的 WcfHelper 中(可能不应该是static不再因为它需要会员_strategyFactory)您像以前一样创建一个频道:

{
    var channel = _strategyFactory.CreateChannel<CarServiceSoapChannel>();

    return method(channel);
}

显然,您需要再次添加所有奇特的 try/finally 内容。


由于您现在应该拥有实例,并且类中的工厂作为成员,因此您可以将服务契约泛型放入您的类中,以方便用户使用:

public class ConnectionToService<TInterface> : where TInterface : class
{
    public TResult ExecuteCommand<TResult>(Func<TInterface, TResult> method)
    {
        var channel = _strategyFactory.CreateChannel<CarServiceSoapChannel>();

        return method(channel);
    }
}

Usage:

var service = new ConnectionToService<ICarService>();

var color = service.ExecuteCommand(s => s.GetColor());
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将接口方法作为参数传递 的相关文章

  • C# 中两种不同类型的列表

    我目前在为客户提供购物车时遇到问题 他希望能够在 CartItems 之间添加文本 所以我想知道是否有某种方法仍然只有一个列表 我的解决方案是有两个列表 其中一个是 IList 类型 在计算购物车的重量和总体价格时会迭代 而另一个 ILis
  • TFS API - 缓慢的 foreach 变更集迭代

    问题背景 我正在使用 TFS api 查询 TFS 服务器上的大范围 1 600 文件 我从每个文件中收集其所有 ChangesetId 然后将其收集在列表中 代码 这是我正在使用的代码 它可以正确生成 QueryHistory 方法中指定
  • 在 C# 中转换 VbScript 函数(Right、Len、IsNumeric、CInt)

    同样 我在 VbScript 中得到了以下代码 您能建议一下 C 中的等效代码吗 Function GetNavID Title getNavID UCase Left Title InStr Title 1 End Function 我已
  • C++11 中具有 C 链接的复杂类型

    我需要将 C 库的标头包含到我的 C 11 代码中 现在 标头提供了涉及大量的例程和数据结构double complex到处都是 例如 include
  • 使用 strcpy 从整数生成指针,无需进行强制转换

    我不明白我做错了什么 我正在学习 C 很抱歉 如果这显然是错误的 但我正在尝试使用uthash http uthash sourceforge net 制作股票及其价格的哈希图 但是当我将股票添加到哈希映射时 我收到上述错误 我所做的就是从
  • 通过 TCP/.NET SSLStream 发送文件很慢/无法正常工作

    我正在编写一个与 SSL 配合使用的服务器 客户端应用程序 通过SSLStream 它必须做很多事情 不仅仅是文件接收 发送 目前 它的工作原理是 只有一个连接 我总是使用从客户端 服务器发送数据SSLStream WriteLine 并使
  • 在 PHP 扩展中,推荐从 std::string 返回值的方法

    我们有一个简单的 PHP 函数 其目的是调用 C 自由函数std string callLibrary std string 并返回其std string返回值 目前看起来是这样的 PHP FUNCTION call library cha
  • .NET:EventHandler 竞争条件修复如何工作?

    以下模式用于在引发事件时避免竞争条件 以防另一个线程取消订阅 MyEvent 使其为空 class MyClass public event EventHandler MyEvent public void F EventHandler h
  • 如何在方法模板中使用模板类型的引用传递参数?

    我目前正在努力编译以下代码 首先是包含带有方法模板的类的头文件 ConfigurationContext h class ConfigurationContext public template
  • 获取不带波形符的泛型类名称[重复]

    这个问题在这里已经有答案了 我正在尝试获取类型名称T使用这个 typeof T Name 班级名称是ConfigSettings 而不是返回ConfigSettings它正在返回ConfigSettings 1 有什么具体原因吗 我怎样才能
  • 如何修复 TcpClient Ip 标头错误校验和

    我正在使用 System Net Sockets TcpClient 类 但每当我通过网络发送自定义数据包时 我都会在wireshark捕获上看到错误的校验和 我该如何修复它 问题是您在网络接口上设置了校验和卸载 这会导致您的网卡计算校验和
  • DataGridView小数不排序

    好吧 我有一个 DataGridView 它的数据绑定如下 dataGridViewChartOre AutoGenerateColumns false dataGridViewChartOre DataSource xml GetOreC
  • “已经有一个与此命令关联的打开的 DataReader,必须先将其关闭。”

    我正在开发需要连接到另一个数据库以获取一些数据的应用程序 为此 我决定使用 SqlConnection reader 等 我需要执行一些查询 例如首先我需要获取某个用户的卡 ID 之后我需要通过该卡 ID 获取一些数据 这是我的代码 reg
  • C++在子类中调用虚方法

    我有以下课程 class A protected A inner public virtual void doSomething 0 class B public A void doSomething if inner NULL inner
  • gcc 删除内联汇编代码

    看起来 gcc 4 6 2 删除了它认为函数中未使用的代码 test c int main void goto exit handler asm volatile jmp 0x0 exit return 0 拆解main 0x0804840
  • C# While 循环与 For 循环?

    在 C 中 一个问题已经困扰我一段时间了 它的 While 和 For 循环之间的实际主要区别是什么 它只是纯粹的可读性吗 在 for 循环中本质上可以做的所有事情都可以在 while 循环中完成 只是在不同的地方 举这些例子 int nu
  • 如何获取数字列的确切类型,包括。规模和精度?

    有没有办法知道列中列的确切类型DataTable 现在我正在这样做 DataTable st dataReader GetSchemaTable foreach DataColumn col in st Columns var type c
  • 在 C# 中设置风扇速度

    我知道以前有人问过这个问题 但我似乎无法让它发挥作用 我已调用以下内容 using System Management using System Management Instrumentation using System Runtime
  • 我可以创建一个 List> 吗?

    我正在尝试创建一个列表WeakReference使用 4 5 泛型实现 这样我就可以避免类型检查和转换WeakReference目标 但 WeakReference
  • 创建进程的多个子进程并维护所有 PID 的共享数组

    我已经分叉了几次 并用 C 创建了一堆子进程 我想将它们所有的 PID 存储在一个共享数组中 PID 的顺序并不重要 例如 我创建了 32 个进程 我想要一个 32 个整数长的数组来存储每个 PID 并且每个进程都可以访问 最好的方法是什么

随机推荐

  • 中缀表示法的有趣行为

    有时 有人试图躲在电脑屏幕后面 试图摆脱女朋友 然而 我发现Scala有时和我的女孩一模一样 这将打印两个列表之间的交集 val boys List Person John Person Kim Person Joe Person Piet
  • MVVM - 分离视图之间的通信

    我试图弄清楚如何执行以下操作 我有一个CustomerListViewModel其中包含一个ObservableCollection
  • 在 Swift 中使用 Tab 键选择下一个 NSTextField

    在 Swift 中 有没有办法通过按键盘上的 Tab 来更改响应者或选择另一个文本字段 笔记 这是填空式申请 我的 VC 创建了一个单词列表 Word 每个单词都有自己的 WordView word wordView WordView 就是
  • Maven 3.5.2 无法将工件部署到 Artifactory,并出现错误 417

    我正在创建简单的pom项目如下
  • 在故事板中使用 UIPageViewController

    有没有一种方法可以在故事板中为 UIPageViewController 配置数据源 委托和视图控制器而无需编写代码 我确实在 UIPageViewController 中看到了数据源和委托的出口 但无法在场景之间建立连接 也无法将额外的控
  • Laravel 5.2:未找到 Imagick 类

    我们正在将 PDF 页面转换为多个单个图像 我们在stackoverflow中找到了一段代码片段 并将其转换为服务类 我们安装了 Imagick 它也显示在 phpinfo 中 然而 在我们的 Laravel 应用程序版本 5 2 中 我们
  • 如何设置 intel_idle.max_cstate=0 来禁用 c 状态?

    我想在我的计算机上禁用 c 状态 我在 BIOS 上禁用了 c state 但没有获得任何结果 不过 我找到了一个解释 大多数较新的 Linux 发行版 在配备 Intel 处理器的系统上 使用 intel idle 驱动程序 可能编译到内
  • 如何从Python列表中的前一个值中减去该值?

    我正在尝试获取列表中的值 例如 1 2 3 并将它们彼此相减 所以它会返回 1 1 因为第一个值是1 2第二个值是2 3 我如何在 python 中实现这一点 我努力了 x y for x y in list 但这会出现 需要多个值才能解包
  • 带有数组赋值的 JavaScript 意外控制台输出;

    在 webkit 浏览器 Chrome 16 0 912 77 和 Safari 5 1 2 7534 52 7 中进行数组分配后 我收到意外的控制台输出 这是我的函数 它演示了该错误 function test var myArray c
  • 即使用户不接受照片,相机意图 onActivityResult 代码也会保存(空白)图像

    当用户单击叉号不接受照片时 它会以与接受拍摄的照片时相同的方式结束意图 它将文件保存到设备库 但它是空白的 单击叉号不应该意味着 resultCode RESULT OK 吗 我还缺少一张支票吗 谢谢 这是代码 等等 我正在保存活动结果之前
  • 如何从 zip 中打开 html 文件?

    有什么方法可以从包含 html 引用的图像的 zip 文件中打开 html 文件吗 我生成带有资源相对路径的 html 但浏览器不会在 zip 文件中找到它们 我必须先将其提取 从拉链打开它是理想的选择 有什么办法可以做到吗 据我所知 只有
  • 创建 Angular/React 应用程序时的 .Net 本地主机服务器

    我正在使用 VS2017 2019 和 NET Core 2 1 来创建Angular or React应用程序 Angular CLI or create react app用于设置一切 以下所有内容都与开发阶段有关 当我们构建 NET
  • 针对数字板难题的优化 CLP(FD) 求解器

    考虑问题从https puzzling stackexchange com questions 20238 explore the square with 100 hops https puzzling stackexchange com
  • let* 和 set 之间的区别?在 Common Lisp 中

    我正在从事一个基因编程爱好项目 我有一个函数 宏设置 当以 setq setf 形式评估时 将生成一个如下所示的列表 setq trees make trees 2 gt x abs x 然后它将绑定到 lambda 函数
  • 如何使用 Swift 在 stderr 上打印?

    我在 Linux 上使用 Swift 2 2 需要在标准错误流上编写一些调试输出 目前 我正在执行以下操作 import Foundation public struct StderrOutputStream OutputStreamTyp
  • 在没有窗口的windows桌面上绘制OpenGL

    我见过这样的事情 我想知道这是否可能 假设我运行我的应用程序 它会显示其下方的渲染结果 所以基本上 在没有窗口的情况下在屏幕上渲染 可能还是谎言 注意 想要在 Windows 和 C 中执行此操作 可以使用您的应用程序在其他应用程序的窗口上
  • Perl 函数中的引用返回值是否更好?

    与返回数组或哈希的引用相比 返回数组或哈希有哪些优缺点 对内存或执行时间有影响吗 两者在功能上有何区别 sub i return an array my a push things in a return a sub i return a
  • cudaMemcpyToSymbol 与 cudaMemcpy [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我试图找出
  • 我应该如何格式化 R mlogit 包的数据?

    我正在使用mlogit与 R 一起打包 使用以下方式导入我的数据后 t lt read csv junk csv header TRUE sep dec 并致电 x lt mlogit data t choice D shape long
  • 将接口方法作为参数传递

    Note 这很可能是非常C 特定语言问题 与以下无关WCF or web services at all 有3方ASMXWeb 服务 用于数据检索 我创建了一个名为的通用方法ExecuteCommand 用于针对 Web 服务的每个请求 该