How to use interface data type without attribute “KnownType” in WCF?

青春壹個敷衍的年華 提交于 2019-12-08 04:09:33

问题


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?


回答1:


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 ServiceKnownTypethat 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!