如何使用没有属性"KnownType"的接口数据类型?在WCF中? [英] How to use interface data type without attribute "KnownType" in WCF?

查看:100
本文介绍了如何使用没有属性"KnownType"的接口数据类型?在WCF中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用的是包含"OperationContract"操作的"ServiceContract". 操作返回或接收的接口参数. 使用服务时,我会收到一条异常消息:

解串器不知道任何映射到该名称的类型.如果您正在使用DataContractSerializer或将与'{%className%}'相对应的类型添加到已知类型列表中,请考虑使用DataContractResolver". >

我可以将KnowTypes的属性添加到接口,但是我的接口项目与实现项目是分离的,并且它们不能具有循环依赖项引用,因此无法声明KnowTypes.

什么是最佳解决方案?

解决方案

我找到了一个解决方案,并且可行!

我正在使用ServiceKnownType加载为DataContract成员实现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!");
        }
    }

用于使用在服务中实现IAnimal接口的CatDog类型:

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

我可以使用属性ServiceKnownType来按接口类型加载类型.

我创建了一个静态类,该类返回所有IAnimal类型:

  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添加到服务接口属性:

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

就是这样!

它将在加载服务时以动态模式加载所有IAnimal已知类型,并且将对CatDog进行序列化,而无需进行任何配置.

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

这篇关于如何使用没有属性"KnownType"的接口数据类型?在WCF中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆