如何使用没有属性"KnownType"的接口数据类型?在WCF中? [英] How to use interface data type without attribute "KnownType" in 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
接口的Cat
和Dog
类型:
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
已知类型,并且将对Cat
和Dog
进行序列化,而无需进行任何配置.
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 ServiceKnownType
that 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屋!