4

可以说我有一些接口:

public interface IFoo {
  IBar DoesStuff();
}
public interface IBar {
  string Thingo { get; }
}

我在整个代码库中使用此代码。IFoo 进程需要移动到不同的系统上(x64 与 x32 的区别),这就是我们使用 WFC 的原因。我的 WCF 服务实现了这个接口。当我创建“服务引用”时,会创建代理存根,但会更改接口。

public interface IFoo {
   object DoesStuff();
}   

我尝试将 IBar/Bar 定义为 DataService 和 DataContract,没有区别。有没有办法使用我的界面生成代理代码?

我在想如果模拟对象可以生成我的接口对象进行测试,那么我不应该能够让服务也兑现它吗?还是做了一些愚蠢和错误的事情?

4

5 回答 5

6

IBar 需要是具体的和 DataContract。WCF 不是关于分布式对象,而是一种传输数据并让服务处理该数据的方法。您不能在 WCF 中返回具有行为的对象。

于 2009-06-24T21:13:43.097 回答
2

我不知道你是否还需要解决方案。下面是我要做的。这里的技巧不是像许多博客建议的那样使用标准的“添加服务引用”,而是使用 Channel Factory 编写自己的客户端代理。在这种情况下,您可以选择重用接口,但根据需要重新定义具体类。如果您需要,很乐意进一步详细说明。

// Service Contract
[ServiceContract(name="a", namespace="b")]
public interface IFoo {
    Bar DoesStuff();
}

// Interface to share
public interface IBar {
    string Thingo { get; }
}

// Server Implementation
public class Bar : IBar
{
    string Thingo { get; set; }
}

// Client Proxy reference IBar interface only but redefine concrete class Bar.
public class Bar : IBar 
{
    public string Thingo
    {
        get { return _thingo; }
        set { _thingo = value; }
    }
    string _thingo;
}


/// Sample channel factory implementation
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;

public abstract partial class ServiceProxyBase<TServiceContract> : IServiceProxy
    where TServiceContract : class 
{
    protected ServiceProxyBase()
        : this(null, null)
    {
    }

    protected ServiceProxyBase(string url, Binding binding)
    {
        var contractName = typeof(TServiceContract).Name;
        var urlConfiguration = string.Format("{0}_Url", contractName);
        var serviceUrl = url ?? ConfigurationManager.AppSettings.ValueOrDefault          (urlConfiguration, string.Empty, true);
        if (serviceUrl.IsNullOrEmptỵ̣())
        {
            throw new Exception(string.Format("Unable to read configuration '{0}'", urlConfiguration));
        }

        var serviceBinding = binding ?? new BasicHttpBinding();
        Factory = new ChannelFactory<TServiceContract>(serviceBinding);

        var serviceUri = new Uri(serviceUrl);

        var endPoint = new EndpointAddress(serviceUri);

        Channel = Factory.CreateChannel(endPoint);
    }

    public virtual void Abort()
    {
        isAborted = true;
    }

    public virtual void Close()
    {
        if (Channel != null)
        {
            ((IClientChannel)Channel).Close();
        }

        if (Factory != null)
        {
            Factory.Close();
        }
    }

    private ChannelFactory<TServiceContract> Factory { get; set; }

    protected TServiceContract Channel { get; set; }

    private bool isAborted = false;
}


public class FooServiceProxy : ServiceProxyBase<IFooServiceProxy>, IFooServiceProxy
{
    public Task<Bar> DoesStuffAsync()
    {
        return Channel.DoesStuffAsync();
    }
}

[ServiceContract(name="a", namespace="b")] // The trick when redefine service contract
public interface IFooServiceProxy
{
    [OperationContract]
    Task<Bar> DoesStuffAsync();
}
于 2013-12-05T11:38:23.017 回答
1

是的。在添加服务引用之前,您需要引用包含该接口的项目。然后接口将被重新使用。对于使用的任何自定义类也是如此 - 如果包含其定义的项目在添加服务引用之前被客户端项目引用,则 WCF 可以重用这些定义。

您还需要转到“添加服务引用”对话框中的“高级”选项卡并勾选“在引用的程序集中重用类型”以使其工作。

于 2009-06-24T21:13:08.967 回答
1

尝试将 Web 服务视为跨平台的。如果您返回它,Java 客户端会如何处理您的接口?

于 2009-06-24T21:16:28.350 回答
0

另一种给猫剥皮的方法。Dominic 使用 KnownType 属性完成了它。在下面查看他的博客。

http://blogs.msdn.com/b/domgreen/archive/2009/04/13/wcf-using-interfaces-in-method-signatures.aspx

于 2013-12-05T11:42:49.510 回答