2009-06-24 6 views
4

일부 인터페이스가 있다고 가정 해 보겠습니다.WCF 서비스에서 인터페이스를 반환하려면 어떻게해야합니까?

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

코드베이스 전체에서이 코드를 사용하고 있습니다. IFoo 프로세스를 다른 시스템으로 옮겨야합니다 (x64와 x32의 차이). 이것이 WFC를 사용하는 이유입니다. 내 WCF 서비스가이 인터페이스를 구현합니다. "서비스 참조"를 만들면 프록시 스텁이 만들어 지지만 인터페이스가 변경됩니다.

public interface IFoo { 
    object DoesStuff(); 
} 

차이점없이 DataService와 DataContract로 IBar/Bar를 정의 해 보았습니다. 인터페이스를 사용하여 프록시 코드를 생성 할 수 있습니까?

mock 객체가 테스트 용 인터페이스 객체를 생성 할 수 있다면 서비스를받을 수 없을 것입니다. 또는 어리석은 무엇을 잘못 했는가?

답변

6

IBar는 구체적이고 DataContract가되어야합니다. WCF는 분산 된 개체가 아니라 데이터를 전송하고 해당 데이터에서 서비스 작업을 수행하는 방법입니다. 동작이있는 WCF의 개체를 반환 할 수 없습니다.

+0

IBar를 구현 한 DataContract로 정의 된 배후 콘크리트 바 객체가 있다는 것이 확실한 경우 첫 번째 구문에서 나온 것이 아닙니다. 반환 된 객체에 동작이 없습니다. 그것은 속성 getters만을 포함합니다. 나는 getter가 메소드라는 것을 알고있다. 당신이 묘사하는 것은 궁극적으로 내가 한 일입니다. 다른 곳에서 처리하고 그 안에있는 데이터로 객체를 반환합니다. 데이터는 인터페이스로 정의됩니다. – Mike

+0

btw 입력 해 주셔서 감사합니다! – Mike

+0

WCF는 네트워크를 통해 개체 또는 인터페이스를 사용할 수 없게 만드는 대신 메시지 교환을 용이하게한다고 생각하십시오. WCF의] DataContract] 항목을 사용하면 클래스의 속성과 필드 사이를 메시지에 매핑하거나 그 반대로 연결할 수 있습니다.실제로 클래스에 연결되는 메시지 (클래스 또는 인스턴스)를 전송하지 않습니다. – Cheeso

1

예. 서비스 참조를 추가하기 전에 인터페이스가 포함 된 프로젝트를 참조해야합니다. 그런 다음 인터페이스가 다시 사용됩니다. 사용 된 모든 사용자 정의 클래스에 대해서도 마찬가지입니다. 정의가 포함 된 프로젝트가 서비스 참조가 추가되기 전에 클라이언트 프로젝트에서 참조되는 경우 WCF는 해당 정의를 다시 사용할 수 있습니다.

또한 서비스 참조 추가 대화 상자의 고급 탭에서 "참조 된 어셈블리에서 유형 재사용"을 선택해야 제대로 작동합니다.

+0

프록시를 생성하기 전에 프로젝트를 참조했습니다. 이미 내 코드베이스를 통해 사용되었습니다. – Mike

+0

내 게시물을 세부 정보와 함께 편집했습니다. 지금 사용해 볼 수 있습니까? –

+0

입력 해 주셔서 감사합니다! 해당 옵션이 이미 선택되었습니다. 명시 적 옵션을 사용하여 재사용 할 특정 어셈블리를 말했지만, 여전히 개체로 돌아옵니다. – Mike

1

웹 서비스를 크로스 플랫폼으로 생각하십시오. Java 클라이언트가 인터페이스를 반환 한 경우 Java 클라이언트는 어떤 작업을 수행합니까?

+0

입력 해 주셔서 감사합니다! 저는 데이터를 전달하려고합니다. ;) 나는 여전히 데이터 중심 인터페이스가 허용되어야한다고 생각하고 적절한 속성으로 표시함으로써 그 목표를 달성 할 수 있습니다. – Mike

+0

SOAP, WSDL, XSD, XML에는 인터페이스 개념이 없습니다. DataContract를 작성하면 사실상 데이터 중심의 인터페이스를 만들 수 있습니다. 전달되는 유일한 것은 데이터입니다. –

2

해결책이 필요한지 잘 모르겠습니다. 아래는 내가 할 수있는 일이다. 여기있는 속임수는 많은 블로그처럼 표준 "add service reference"를 사용하지 않고 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(); 
} 
0

고양이를 피부로 또 다른 방법. Dominic은 KnownType 속성을 사용하여이 작업을 수행했습니다. 아래 그의 블로그를 확인하십시오.

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

+1

[링크 전용 답변] (http://meta.stackoverflow.com/tags/link-only-answers/info)은 권장하지 않으므로 SO 답변은 솔루션 검색의 종점이어야합니다 (시간이 지남에 따라 부실 해지는 경향이있는 참조의 또 다른 중간 기착). 링크를 참조 용으로 유지하면서 독립형 시놉시스를 여기에 추가하는 것을 고려해보십시오. – kleopatra

관련 문제