【问题标题】:How to make two different service references implement the same interface?如何让两个不同的服务引用实现相同的接口?
【发布时间】:2014-07-01 14:14:07
【问题描述】:

我有以下场景:

  • 服务 Web 项目(Web 应用程序)

    • ServiceA.svc
    • ServiceB.svc
    • ExceptionResponseMessage.cs
  • 接口 Web 项目(Web 应用程序)

    • 服务参考:
      • ServiceAServiceReference
      • ServiceBServiceReference

在两个服务(A 和 B)中,我都有返回 ExceptionResponseMessage 类的方法。在接口web项目中,我称之为“客户端”,为了方便参考,这个类生成了两次:

  • ServiceAServiceReference.ExceptionResponseMessage
  • ServiceBServiceReference.ExceptionResponseMessage

我想在我的客户端中创建一个函数来处理响应消息以查看是否有任何错误并正确处理。因为我有两个类的副本,所以我必须创建两个方法:

public static void HandleError(ServiceAServiceReference.ExceptionResponseMessage ex)
{
    (Method Implementation here)
}

public static void HandleError(ServiceBServiceReference.ExceptionResponseMessage ex)
{
    (Method Implementation here)
}

我想避免这种情况,所以我在不同的类库项目中创建了一个接口,服务和客户端项目都可以访问它。 ExceptionResponseMessage 实现了这个接口。

问题是客户端为“ExceptionResponseMessage”生成的类没有实现接口。我什至在接口和对象中创建了一个自引用的“InnerException”属性,如下所示:

public interface IExceptionResponseMessage {
    IExceptionResponseMessage InnerException { get; set; }
}

public class ExceptionResponseMessage : IExceptionResponseMessage
{
    public IExceptionResponseMessage InnerException { get; set; }
}

但是当我检查客户端生成的对象时,它说 InnerException 属性是 Object 类型,这表明该接口在客户端中没有得到尊重。

有谁知道如何让客户端类实现接口?

【问题讨论】:

  • 客户端是否有包含接口和实现的程序集?如果没有,那么您必须在客户端上创建一个抽象。
  • 客户端只有带有接口的程序集。该实现由服务参考自动生成。
  • 对,但是如果你有实际的类程序集,它会使用 WCF...(我认为...)
  • 否则你将不得不处理自定义类型。
  • 问题是我的 ExceptionResponseMessage 继承自 ResponseMessage 主类。服务器可以使用此类及其所有后代,但有些类引用了服务项目中的类,我无法将其放入这个公共库中。

标签: c# .net wcf interface


【解决方案1】:

通常我不推荐使用dynamic,因为存在运行时失败的风险,但这里可能值得冒险,因为您已经在错误处理程序中:

public static void HandleError(dynamic ex)
{
    //(Method Implementation here)
}

这样您就可以使用异常类型共有的属性和方法。如果您想要智能感知,您可以在开发过程中对其进行强类型化,并在处理程序完成后更改为dynamic

风险在于,如果您使用不存在的方法/属性,它会在运行时失败。您可以通过处理Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 异常来减少该错误的影响:

public static void HandleError(dynamic ex)
{
    try
    {
        //(Method Implementation here)
    }
    catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException rbex)
    {
        // do something (or ignore)
    }
    // all other exceptions are bubbled up
}    

一个更安全的解决方案是保持你的重载,并使dynamic方法private

public static void HandleError(ServiceAServiceReference.ExceptionResponseMessage ex)
{
    HandleErrorDynamic(ex);
}

public static void HandleError(ServiceBServiceReference.ExceptionResponseMessage ex)
{
    HandleErrorDynamic(ex);
}
private static void HandleErrorDynamic(dynamic ex)
{
    //(Method Implementation here)
}    

这样您就可以控制传递给动态方法的内容,并可以编写单元测试来防止运行时错误。

【讨论】:

  • 这是一个有趣的解决方案,但是你自己有没有说过,在编译类型中放松类型检查是很危险的,但如果我找不到更好的解决方案,我可能会尝试一下。跨度>
  • 你最好重载HandleError方法并从那里调用公共代码。
【解决方案2】:

放弃返回类实例的服务方法,而是返回string xml 响应,然后可以将其序列化到您正在使用的异常响应类中。

【讨论】:

  • 这是一个有趣的解决方案,但不幸的是,当时我的项目结构将发生更大的变化。不过还是谢谢。
  • @Marlon 我想这很可能是你的答案。我从事 Web 服务已有十多年了,我总是更喜欢(当我有机会时)简单地使用可版本化的 Xml。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多