2010-03-09 5 views
5

나는 여러 계약을 가진 서비스를 보유하고 있습니다.WCF 중복 메소드 이름을 가진 여러 계약

[ServiceContract] 
public partial interface IBusinessFunctionDAO { 

    [OperationContract] 
    BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract] 
public partial interface IBusinessUnitDAO { 

    [OperationContract] 
    BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
} 

다음과 같이 각 인터페이스를 명시 적으로 구현했습니다. 그래서 이것은 잘 컴파일하고 완벽하게 유효한 당신이 볼 수 있듯이

public class TrackingTool : IBusinessFunctionDAO, IBusinessUnitDAO { 

    BusinessFunction IBusinessFunctionDAO.GetBusinessFunction(Int32 businessFunctionRefID) { 
     // implementation 
    } 
    IEnumerable<Project> IBusinessFunctionDAO.GetProjects(Int32 businessFunctionRefID) { 
     // implementation 
    } 

    BusinessUnit IBusinessUnitDAO.GetBusinessUnit(Int32 businessUnitRefID) { 
     // implementation 
    } 
    IEnumerable<Project> IBusinessUnitDAO.GetProjects(Int32 businessUnitRefID) { 
     // implementation 
    } 
} 

나는 두 GetProjects (INT) 방법을 가지고 있지만, 각각의 하나는 명시 적으로 구현된다. 이 문제는 제가 실제로 이것을 서비스로 시작할 때 발생합니다. TrackingTool에 이미 GetProject 정의가 포함되어있어 오류가 발생합니다. 그것이 사실이지만 다른 서비스 계약의 일부입니다. WCF는 메서드 이름을 생성 할 때 서비스 계약을 구분하지 않습니까? 서비스 계약을 구별 할 수있는 방법이 있습니까?

내의 app.config는 어떤 도움을 주시면 감사하겠습니다이

<service name="TrackingTool"> 
    <endpoint address="BusinessUnit" contract="IBusinessUnitDAO" /> 
    <endpoint address="BusinessFunction" contract="IBusinessFunctionDAO" /> 
</service> 

것 같습니다.

감사합니다, 라울

+0

@monO는 답변에서 언급했듯이 실제 개별 메소드 이름은 서비스 클래스에서 고유해야합니다. WSDL은 인터페이스와 모든 것에 대해 아무것도 모르고 다른 매개 변수로 메소드 오버로딩을 허용하지 않습니다. 이러한 메소드 이름을 전체 서비스 클래스에서 고유하게 만들 필요가있다. –

+0

아, WSDL이 실제로 어떻게 생성되었는지 읽어야합니다. 각 계약에는 WSDL 내부에 자체 네임 스페이스가 있다고 생각했습니다. – HaxElit

+0

... 실제로 나는 그것도 매우 혼란 스럽다. @marc_s : WSDL은 다른 인터페이스에 대해 알고 있습니다. 그들은 전용 바인딩으로 전용 포트로 노출됩니다. – Alex

답변

10

나는 그 이유를 발견했다고 생각합니다. 우리는 다음과 같은 한 네임 스페이스 : 다음 TNS를 정의하는 XSD에서 다음

<wsdl:message name="IBusinessUnitDAO_GetBusinessUnitProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetBusinessUnitProjects" /> 
</wsdl:message> 
<wsdl:message name="IBusinessFunctionDAO_GetBusinessFunctionProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetBusinessFunctionProjects" /> 
</wsdl:message> 

다음 WSDL에서 함수는 다음과 같이 노출됩니다

<xs:element name="GetBusinessUnitProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessUnitRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

<xs:element name="GetBusinessFunctionProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessFunctionRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

그래서 충돌 비록 이유하여 서비스는 wsdl 파트 요소가 모두 동일한 네임 스페이스에 있기 때문에 두 가지 다른 계약을 노출합니다. 따라서 동일한 두 개의 함수 이름을 만들면 동일한 이름의 중복 요소가 만들어져 문제가 발생합니다. 따라서 문제의 해결 방법은 각 서비스 계약에 네임 스페이스 특성을 추가하는 것입니다. 우리가 원래의 서비스 계약을 맺고 그렇게 수정하면.

[ServiceContract(Namespace="Tracking/BusinessFunction")] 
public partial interface IBusinessFunctionDAO { 

    [OperationContract] 
    BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract(Namespace="Tracking/BusinessUnit")] 
public partial interface IBusinessUnitDAO { 

    [OperationContract] 
    BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
} 

WSDL을 생성 할 때 우리가 생성 한 각 네임 스페이스에 대해 WSDL을 얻습니다. 이 네임 스페이스에는 각 포트가 모든 조작 및 요소로 식별됩니다. 그래서 우리의 별도의 WSDL의 각 내부에서 우리는 다음과 같은 얻을 :

//File: Tracking.BusinessFunction.wsdl 
<wsdl:message name="IBusinessFunctionDAO_GetProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetProjects" /> 
</wsdl:message> 

//File: Tracking.BusinessUnit.wsdl 
<wsdl:message name="IBusinessUnitDAO_GetProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetProjects" /> 
</wsdl:message> 

당신은 둘 다 같은 요소 이름을 볼 수 있지만, 서로 다른 네임 스페이스 서로 요소가 더 이상 충돌 때문이다.우리는 XSD에서 살펴 경우 그들은 지금 정의 같은 요소를 가지고 있지만 다른 매개 변수와 함께 :

//File: Tracking.BusinessFunction.xsd 
<xs:element name="GetProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessFunctionRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

//File: Tracking.BusinessUnit.xsd 
<xs:element name="GetProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessUnitRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

그래서 내 원래의 질문에 대한 대답은 그렇게하지 않도록 각 서비스 계약은 별도의 공간에 살고 만드는 것입니다 충돌하는 포트 요소가 있습니다. 이는 또한 계약의 일부를 배포하는 경우 관리가 더 용이 한 별도의 WSDL에서 계약을 체결 할 수있는 유연성을 제공합니다.

+0

단지 후속 조치입니다. 인터페이스가 명시 적으로 정의 된 경우 생성되는 요소 이름은 이어야합니다. 그러면 메시지 부분 요소와의 충돌이 제거됩니다. 이견있는 사람 ? – HaxElit

+0

좋은 하나! 세부 사항을 공유해 주셔서 감사합니다! – Alex

0

과 같이, 충돌을 제거하기 위해 이름이 같은 두 가지 방법에 대해 OperationContract를 속성에 Action 속성을 설정하십시오 : 당신은 별칭을 사용하여 시도 할 수

[ServiceContract] 
public partial interface IBusinessFunctionDAO { 

[OperationContract] 
BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

[OperationContract(Action="GetBusinessFunctionProjects")] 
IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract] 
public partial interface IBusinessUnitDAO { 

[OperationContract] 
BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

[OperationContract(Action="GetBusinessUnitProjects")] 
IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
}