2017-02-05 18 views
1

"OperationContract"작업이 포함 된 "ServiceContract"를 사용하는 경우. 작업 반환 또는 수신 인터페이스 매개 변수입니다. 서비스를 사용할 때 예외 메시지가 나타납니다 :WCF의 "KnownType"특성없이 인터페이스 데이터 형식을 사용하는 방법은 무엇입니까?

"디시리얼라이저는이 이름에 매핑되는 모든 유형에 대해 알지 못합니다. DataContractSerializer를 사용하거나 '{ % className %} '을 (를) 알려진 유형 목록에 추가하십시오.

KnowTypes의 속성을 인터페이스에 추가 할 수 있지만 인터페이스 프로젝트가 구현 프로젝트와 분리되어 있으며 원형 의존성 참조를 가질 수 없으므로 KnowTypes를 선언 할 수 없습니다.

최상의 솔루션은 무엇입니까?

+0

다시 디자인해야하는 것처럼 들립니다. 인터페이스 프로젝트는 구현에 의존하지 않아야합니다. – Crowcoder

+0

이것은 내가 피하려고하는 것입니다. 내 디자인은 인터페이스와 구현이 분리되어 있으므로 인터페이스에 KnownTypes 특성을 사용할 수 없습니다. –

답변

0

해결책을 찾았습니다.

나는 DataContract 구성원에 대해 ServiceKnownType을 구현하는 유형을로드하는 ServiceKnownType을 사용하고 있습니다. 예를 들어

:

나는 동물의 인터페이스를 가지고 :

public interface IAnimal 
{ 
    string Name { get; } 

    void MakeSound(); 
} 

및 구현 (인터페이스 구현 유형 모르는) :

public class Cat : IAnimal 
{ 
    public string Name =>"Kitty"; 

    public void MakeSound() 
    { 
     Console.WriteLine("Meeeee-ow!"); 
    } 
} 

    public class Dog : IAnimal 
    { 
     public string Name => "Lucy"; 

     public void MakeSound() 
     { 
      Console.WriteLine("Wolf Wolf!"); 
     } 
    } 

CatDog 유형을 사용하기 위해를가 서비스에 IAnimal 인터페이스를 구현하십시오.

public interface IAnimalService: IAnimalService 
{ 
    IAnimal GetDog(); 
    void InsertCat(IAnimal cat); 
} 

인터페이스 유형별로 유형을로드하는 ServiceKnownType 속성을 사용할 수 있습니다.

public static class AnimalsTypeProvider 
{ 
    public static IEnumerable<Type> GetAnimalsTypes(ICustomAttributeProvider provider) 
    { 
     //Get all types that implement animals. 
     //If there is more interfaces or abtract types that been used in the service can be called for each type and union result    
     IEnumerable<Type> typesThatImplementIAnimal = GetAllTypesThatImplementInterface<IAnimal>(); 

     return typesThatImplementIAnimal; 
    } 

    public static IEnumerable<Type> GetAllTypesThatImplementInterface<T>() 
    { 
     Type interfaceType = typeof(T); 
     //get all aseembly in current application 
     var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
     List<Type> typeList = new List<Type>(); 
     //get all types from assemblies 
     assemblies.ToList().ForEach(a => a.GetTypes().ToList().ForEach(t => typeList.Add(t))); 

     //Get only types that implement the IAnimal interface 
     var alltypesThaImplementTarget = 
      typeList.Where(t => (false == t.IsAbstract) && t.IsClass && interfaceType.IsAssignableFrom(t)); 


     return alltypesThaImplementTarget; 
    }   
} 

및 서비스 인터페이스 속성에 클래스 AnnimalsTypeProvider 및 방법 GetAnimalsTypes를 추가 :

나는 정적 모든 IAnimal 형태를 돌려주는 클래스 생성

[ServiceContract] 
[ServiceKnownType("GetAnimalsTypes", typeof(AnimalsTypeProvider))] 
public interface IServicesServer : IAnimalService 
{ 
    IAnimal GetDog(); 
    void InsertCat(IAnimal cat); 
} 

을하고 바로 그거야!

서비스를로드하는 동안 알려진 모든 유형이 동적 모드로로드되고 어떤 구성도없이 CatDog을 직렬화합니다.