如何在WCF中使用没有属性“KnownType”的接口数据类型?

时间:2017-02-05 17:04:09

标签: c# wcf datacontractserializer datacontract

如果我正在使用包含“OperationContract”操作的“ServiceContract”。 操作返回或接收的接口参数。 当我使用该服务时,我收到一条异常消息:

“反序列化器不知道任何映射到此名称的类型。如果您使用的是DataContractSerializer,请考虑使用DataContractResolver,或者将对应于'{%className%}'的类型添加到已知类型列表中。” p>

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

什么是最佳解决方案?

2 个答案:

答案 0 :(得分:0)

不幸的是,这是不可能的。类似的问题已经被问到:Using Interfaces With WCF

答案 1 :(得分:0)

我找到了一个解决方案并且它已经有效了!

我使用ServiceKnownType加载了为ServiceKnownType成员实施DataContract的类型。

例如:

我有动物界面:

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!");
        }
    }

使用在服务中实现Cat接口的DogIAnimal类型:

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