If I'm using "ServiceContract" that contains "OperationContract" operations. The operation return or received interface parameters. When I'm using the service I get an exception message:
"The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver if you are using DataContractSerializer or add the type corresponding to '{%className%}' to the list of known types".
I can add the attribute of KnowTypes to the interface but my interface project is separated from the implementation project and they cannot have circular dependency reference so it's not possible to declare KnowTypes.
What is the best solution?
I found a solution and it's worked!
I'm using ServiceKnownType
that load the types that implement the ServiceKnownType
for DataContract
members.
For example:
I have animal interface:
public interface IAnimal
{
string Name { get; }
void MakeSound();
}
and implementation (interface does not know the implementation types):
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!");
}
}
For using the Cat
and Dog
types that implement the IAnimal
interface in the service:
public interface IAnimalService: IAnimalService
{
IAnimal GetDog();
void InsertCat(IAnimal cat);
}
I can use the attribute ServiceKnownType
that will load the type by interface type.
I Created a static class that return all the IAnimal
types:
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;
}
}
and adding the class AnnimalsTypeProvider
and method GetAnimalsTypes
to the service interface attribute:
[ServiceContract]
[ServiceKnownType("GetAnimalsTypes", typeof(AnimalsTypeProvider))]
public interface IServicesServer : IAnimalService
{
IAnimal GetDog();
void InsertCat(IAnimal cat);
}
and that's it!
It will load all the IAnimal
known type in dynamic mode while loading the service and it will serialize the Cat
and Dog
without any configuration whatsoever.
来源:https://stackoverflow.com/questions/42054816/how-to-use-interface-data-type-without-attribute-knowntype-in-wcf