如何在WCF中使用没有属性“KnownType”的接口数据类型?
如果我正在使用包含“OperationContract”操作的“ServiceContract”。 操作返回或接收接口参数。 当我使用该服务时,我收到一条exception消息:
“反序列化器不知道映射到此名称的任何类型。如果使用DataContractSerializer或将与'{%className%}’对应的类型添加到已知类型列表中,请考虑使用DataContractResolver”。
我可以将KnowTypes的属性添加到接口,但我的接口项目与实现项目分离,并且它们不能具有循环依赖性引用,因此无法声明KnowTypes。
什么是最好的解决方案?
不幸的是,这是不可能的。 类似的问题已经被问到: 使用WCF接口
我找到了一个解决方案并且它有效!
我正在使用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
接口的Cat
和Dog
类型:
public interface IAnimalService: IAnimalService { IAnimal GetDog(); void InsertCat(IAnimal cat); }
我可以使用ServiceKnownType
属性,它将按接口类型加载类型。
我创建了一个返回所有IAnimal
类型的静态类:
public static class AnimalsTypeProvider { public static IEnumerable 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 typesThatImplementIAnimal = GetAllTypesThatImplementInterface(); return typesThatImplementIAnimal; } public static IEnumerable GetAllTypesThatImplementInterface() { Type interfaceType = typeof(T); //get all aseembly in current application var assemblies = AppDomain.CurrentDomain.GetAssemblies(); List typeList = new List (); //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
已知类型,并且它将序列化Cat
和Dog
而无需任何配置。