2010-07-26 2 views
6

제네릭 인터페이스를 사용하는 메서드가 포함 된 서비스 계약을 구현하려고하는데 일반 인터페이스 자체에 인터페이스 매개 변수가 제공됩니다. 내가 ServiceKnownType와 서비스 인터페이스를 장식 한, 나는 일반 KnownType와 서비스 구현을 장식 한, 나는 일반 KnownType와 datacontract 구현 장식 한 : 그것은 보인다 때문에 공식적으로WCF : 일반 인터페이스의 직렬화가 가능합니까?

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallbacks))] 
[ServiceKnownType(typeof(Batch<object>))] 
[ServiceKnownType(typeof(Command))] 
public interface IActions 
{ 
    [OperationContract] 
    IResponse TakeAction(IBatch<ICommand> commands); 
} 

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)] 
[KnownType(typeof(Batch<object>))] 
[KnownType(typeof(Command))] 
internal class Actions : IActions 
{ 
} 

[DataContract] 
[KnownType(typeof(Command))] 
public class Batch<T> : IBatch<T> 
{ 
} 

을, 나는 배치가있다 한 번만 제네릭 형식에 대한 knowntype을 표현할 수 있습니다. BatchOfanyType을 방출하는 것처럼 보이지만이를 처리하는 방법을 모르겠습니다.

예외는 "KnownTypeAttribute 특성을 사용하거나 DataContractSerializer에 전달 된 알려진 형식 목록에 추가하여 알려진 형식 목록에 정적으로 알려져 있지 않은 형식을 정적으로 추가하는 것입니다."

잘못된 것이 있습니까? 인터페이스의 일반 인터페이스는 지원되지 않습니까? 레코드의 경우이 프로젝트를 위해 C# 2.0 및 .NET 3.0에 있습니다.

답변

12

실제 계약서에 인터페이스를 사용할 수 있습니다. 단, 약간의 조정만으로 알려진 유형을 포함하는 경우에는 아래를 참조하십시오.

분명히 제네릭 형식 매개 변수로 인터페이스를 사용하는 것은 C# 3.0에 비해 너무 먼 다리입니다. 알려진 유형 속성을

으로 변경했습니다.
[ServiceKnownType(typeof(Batch<Command>))] 
public interface IActions 
{ 
} 

어떤 점이 효과가 있습니다. 직렬화 및 역 직렬화 자체가 작동하지만 다음이 예외에 직면하고 있습니다 :

타입 입력 할 'Batch`1 [명령]' 'IBatch`1 [ICommand의]를'개체를 캐스팅 할 수 없습니다.

해당 캐스트가 작동하려면 C# 4.0에 도입 된 제네릭 형식 공분산에 대한 언어 지원이 필요합니다. 그것이 비록 C# 4.0에서 작동하려면 분산 수정을 추가해야 할 것 :

public interface IBatch<out T> 
{ 
} 

은 다음 그것은 완벽하게 작동합니다 ... 불행하게도 당신이 C# 4.0을 사용하고 있지.

서비스 계약에서 인터페이스 사용에 대한 마지막 한 가지 : 서비스 참조를 생성하는 경우 원본 인터페이스 유형이 메타 데이터의 일부가 아니기 때문에 모든 인터페이스 매개 변수를 object으로 입력합니다. 어셈블리 참조를 통해 계약을 공유하거나 생성 된 프록시를 수동으로 리팩터링하여 수정할 수 있지만 WCF의 인터페이스를 사용하면 가치가있는 것보다 더 많은 문제가 발생할 수 있습니다.

+0

네, C# 4.0에서 공분산을 생각할 때 사용하고있는 플랫폼에서 편집했습니다. 아, 업 그레 이드. – bwerks

2

WCF는 SOA 메시지 기반 시스템으로, XML 스키마로 표현할 수있는 직렬화 된 XML 형식으로 모든 데이터를 전송할 수 있습니다.

불행히도 XML 스키마는 인터페이스 나 제네릭 중 어느 것도 알지 못하므로 일반적으로이를 직렬화 할 수 없습니다. 구체적인 유형을 사용해야합니다.

+0

WCF는 그러한 직렬화는 충분히 제네릭을 이해하지 (나는 그것을 한 적이). 인터페이스에 대한 귀하의 의견이 정확합니다. – RQDQ

+0

@RQDQ 그걸 보여줄 장소가 있니? 블로그, CodeProject 기사 또는 무엇인가? 그것을보고 사랑해! –

+1

@RQDQ : 실제로는 완전히 정확하지 않습니다. 인터페이스 자체를 직렬화 할 수는 없지만 사용 된 구체적인 유형은 * 될 수 있습니다. '까다로운'부분은 인스턴스화 할 구체 유형을 알아야하기 때문에 비 직렬화입니다. 그러나 직렬화 된 데이터에는 충분한 정보가 포함되어 있습니다. – Thorarin

1

인터페이스를 직렬화 할 수 없습니다. 인터페이스는 객체가 아니라 계약을 정의합니다. 나는 이것에 대한 한 가지 예외가 ISerializable 인터페이스라고 생각한다.

+1

"ISerializable'"을 직렬화 할 때 실제로는 그렇지 않습니다. 'ISerializable'은 다른 것을 직렬화하는데 사용되는 인터페이스입니다. –

+0

@ John. 당신이 올바른지. 여전히 인터페이스를 직렬화하지 않고 ISerializable을 구현하는 객체를 직렬화하는 데 사용되는 계약에 동의하는 것입니다. 방금 완성도를 위해 추가했습니다. – Mike

1

제네릭은 일련 번호를 지정할 수 있지만 특정 제한 사항이 있습니다.

[DataContract] 
public class Foo<T> 
{ 
    [DataMember] 
    public T Value { get; set; } 
} 

와 서비스 계약 :

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    Foo<String> GetData(); 
} 

와 서비스 구현 :

public class Service1 : IService1 
{ 
    public Foo<string> GetData() 
    { 
     return new Foo<string>() { Value = "My test string" }; 
    } 
} 

상기 서비스에 대한 서비스 참조 번호를 설정 한 후, 예를 들어, 데이터 계약 주어진 코드를 실행할 수 있습니다 :

ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(); 

ServiceReference1.FooOfstring temp = client.GetData(); 

MessageBox.Show(temp.Value); 

그리고 "내 테스트 문자열"메시지 상자가 표시됩니다.

서비스 자체는 일반적인 것은 아니지만 사용되는 데이터 계약은 다음과 같습니다. 또한, 클라이언트 측에서 생성 된 데이터 계약은 일반이 아니라 문자열 형식의 속성 값을 가진 "평평"클래스 :

[System.Runtime.Serialization.DataMemberAttribute()] 
public string Value 
{ 
    get {...} 
    set {...} 
} 
관련 문제