WCF和客户端应用程序中的模棱两可引用

7

我已经成功复现了一个错误,并在一个类似于生产代码结构的测试项目中进行了测试。它由三个简单的项目组成:

Common(类库):

namespace Common
{
    public enum PrimaryColor
    {
        Red,
        Green,
        Blue
    };
}

Library(WCF服务库),它引用了Common:

using Common;

namespace Library
{
    [ServiceContract]
    public interface ILibrary
    {
        [OperationContract]
        PrimaryColor GetColor();
    }

    public class Library : ILibrary
    {
        public PrimaryColor GetColor()
        {
            return PrimaryColor.Red;
        }
    }
}

ClientApp(控制台应用程序),它引用了Common,并且具有对名为“LibraryServiceReference”的Library的服务引用:

using Common;
using ClientApp.LibraryServiceReference;

namespace ClientApp
{
    class Program
    {
        static void Main(string[] args)
        {
            LibraryClient client = new LibraryClient("WSHttpBinding_ILibrary");
            PrimaryColor color = client.GetColor();
        }
    }
}

ClientApp和Library中的app.config文件是自动生成的,我没有修改过它们,并且我没有更改ClientApp中LibraryServiceReference的默认配置。

当我编译这个解决方案时,我在ClientApp项目中遇到了以下错误:

Error 1

'PrimaryColor' is an ambiguous reference between 'Common.PrimaryColor' and 'ClientApp.LibraryServiceReference.PrimaryColor'

错误 2

Cannot implicitly convert type 'ClientApp.LibraryServiceReference.PrimaryColor' to 'Common.PrimaryColor'. An explicit conversion exists (are you missing a cast?)

请帮我解决这个问题。

10个回答

4
请确保在添加服务引用配置服务引用高级选项中选择重用所有引用程序集中的类型

enter image description here


3

这是因为您正在构建x64而不是“AnyCpu”。我现在遇到了这个问题,正在试图弄清楚它是否是一个错误或者它是否是预期的行为。


你的回答是一条评论,而不是一个答案。 - Matsmath
1
我不同意。在我的项目中,我将它从x64切换到AnyCpu,模糊的引用就消失了。虽然我不是这方面的专家,但我认为当项目设置为x64时,在生成代理代码时存在一个错误。我认为由于类型已经被预编译,代理生成只能反向编译它,并生成代理端的类副本。而当它是AnyCpu时,它可以自行解开类型。我在微软工作,认识其中一位编写WCF的人,他甚至说不明白为什么AnyCpu可以工作而x64不能。 - eric frazer
@ericfrazer 你有没有进一步研究这个问题:是bug还是预期行为?将我的DLL从x64切换到AnyCPU解决了这个问题。我会将其重写为答案并标记它,因为它解决了这个问题。 - markf78
1
@ericfrazer 请确保在你的回答中添加显而易见的“假设你已经启用了‘重用引用程序集中的类型…’”以使其100%正确。 - markf78
@ericfrazer,你在这方面有进展吗?我选择了“在引用的程序集中重用类型”,但没有成功! - metoyou

1
  1. 将您的枚举装饰成这样:

    namespace Common
    {
        [DataContract]
        public enum PrimaryColor
        {
            [EnumMember]
            Red,
            [EnumMember]
            Green,
            [EnumMember]
            Blue
        };
    }
    
  2. 更新您的服务引用(并检查重用类型,就像Mark所说的那样)。

  3. 重新构建您的客户端代码。


帮了我大忙!我漏掉了[EnumMember]属性,使用这个枚举的类型也重复了!再次感谢! - Darxis

1
我曾多次遇到这个问题,而且出现的方式总是无法预测!这一次,我想分享一下我是如何"解决"它的。
我使用的是Visual Studio 2013,但也曾经在低版本中遇到过此问题。
这个模糊引用似乎是自动出现的。我没有做任何特别的事情来引起它。在最近的一次中,我正在调试一些代码,突然间就出现了7个、22个、然后是49个错误,全部都是同样的性质。
我完全删除了服务引用,然后重新添加了它。仅仅修改重复使用的类型并没有起到任何作用。我的解决方案中有一个WCF服务、类库、UI和控件库。我还从一些类库的代码中移除了using。
这是一个极为麻烦的问题,幸好只是每隔几周才会出现一次。为什么这样做有效呢?超出了我的能力范围。我感同身受!希望这可以帮到你。在这种情况下,当我打开一些xaml页面的代码时,错误又出现了。

enter image description here


我曾经看到过这样的情况,当将引用库的服务引用添加到客户端应用程序中时,没有先在客户端应用程序中添加相同的引用,并检查重用类型。 - JMIII

0

听起来你控制着客户端和服务器代码。为什么要创建一个服务引用,是有特定的原因还是觉得这样更容易一些呢?

在你控制客户端和服务器端应用程序的双方的项目中,最好创建一个"合同程序集"(可能是你的常规程序集)。其中包含与合同相关的接口和对象,并且应该由你的客户端和服务器端引用。为了与服务通信,客户端使用ChannelFactory创建代理类,没有必要使用专用的WCF客户端。

例子:

ChannelFactory<ISampleService> factory = new ChannelFactory<ISampleService>("Binding_from_config");

ISampleService sampleService = factory.CreateChannel();

sampleService.SomeCall();

factory.Close();

工厂模式也使它成为通过IoC注入代理的理想选择。

引用公共程序集的好处优于创建服务引用:

  • 没有歧义的引用,因为不需要自动生成类。
  • 每次更改合同时都不必更新服务引用。

0

说实话,我在将我的数据契约移动到一个单独的库后遇到了同样的错误。多次更新服务引用并尝试所有组合的程序集重用设置,但都无济于事。

最终解决方法是:1)重新启动Visual Studio;2)更新服务引用。服务定义中Reference.cs中的自动生成代码看起来非常不同,并且没有复制我的数据契约类。它使用了我的库中的正确引用。因此,IDE中可能会缓存某些内容。

希望对其他人有所帮助。


0
我可以通过右键单击服务引用,然后从“在所有引用的程序集中重用类型”更改为“在指定的引用程序集中重用类型”,然后检查特定的公共程序集来解决这个问题。

0
只需从ClientApp项目中删除对Common项目的引用,错误就会消失。当您为服务创建代理时,所有依赖于服务的代码都必须注入到代理中。如果您希望您的类型与服务端上的类型相同,只需在生成代理代码时启用“重用类型”选项(否则它们将被放置在不同的命名空间下)。

-1
问题在于PrimaryColor同时存在于Common和ClientApp.LibraryServiceReference中,而你的类引用了这两个命名空间。
为了解决这个问题,可以显式地引用所需的实例,例如: Common.PrimaryColor color = .... 或者设置一个别名: using Service = ClientLibraryServiceReference; ... Service.PrimaryColor color = ......

@DavidRead 这将使我需要编写一个转换方法来在Client.PrimaryColor和Service.PrimaryColor之间进行转换,这会增加我的工作量。 如果服务中有数百个不同的类需要在客户端代码中引用,你怎么看? - CuriousBenjamin
我只剩下手动编辑reference.cs文件的选项了,没什么别的办法。 无法找出代码中的潜在问题。需要更多有帮助的大脑.. :) - CuriousBenjamin

-2

在创建服务引用时,有没有一些选项说类似于:“在生成的服务契约中包含常见类型”?

我认为在您的服务引用中,这些类是“复制”的,这就是为什么会出现此错误的原因。检查生成的服务文件,删除它们,然后使用“添加服务引用”再次添加它们,并查看那里的选项。

编辑

虽然我几乎确定Type PrimaryColor在公共项目和您的服务引用中都定义了两次,但您还可以尝试在clientApp中执行以下操作(更明确地指定PrimaryColor类型):

Common.PrimaryColor color = client.GetColor();

抱歉,它没有帮助到您... :( @youpTube - CuriousBenjamin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接