【问题标题】:How to use interface data type without attribute "KnownType" in WCF?如何在 WCF 中使用没有属性“KnownType”的接口数据类型?
【发布时间】:2017-02-05 17:04:09
【问题描述】:

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

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

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

什么是最好的解决方案?

【问题讨论】:

  • 听起来你需要重新设计。您的接口项目不应依赖于实现。
  • 这是我试图避免的。我的设计在接口和它的实现之间有分离,所以我不能在接口上使用 KnownTypes 属性。
  • 不幸的是,这是不可能的。类似的问题已经被问过:stackoverflow.com/questions/4192048/…

标签: c# wcf datacontractserializer datacontract


【解决方案1】:

我找到了解决方案,并且成功了!

我正在使用ServiceKnownType 加载实现ServiceKnownTypeDataContract 成员的类型。

例如:

我有动物界面:

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 而无需任何配置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 2011-09-04
    • 1970-01-01
    相关资源
    最近更新 更多