2012-11-17 87 views
2

我有以下结构:WCF调用失败

public class DerivedClass : List<BaseClass> 
{ 
    //Some helper methods used against the List of BaseClass properties 

    //Methods 
    public List<BaseClass> GetListOfBaseClasses() 
    { 
     return (List<BaseClass>)this; 
    } 
} 

我的WCF服务所知道的BaseClass的对象,但客户端导出它作为一个通用的清单,现在当我尝试调用服务,像这样:

DerivedClass classD; 
FillData(classD) 
List<BaseClass> baseClassList = classD.GetListOfBaseClasses(); 

using (IService myService = ObjectFactory.GetMyService()) 
{ 
     myService.DoSomething(baseClassList); //Method is expecting "List<BaseClass>" 
} 

我得到以下异常:

类型 'DerivedClass' 与数据c ontract name'[some URI text]'不是 预计。考虑使用DataContractResolver或将静态已知的任何类型 添加到已知类型的列表中 - 例如,使用KnownTypeAttribute属性的 或将它们添加到传递给DataContractSerializer的已知类型的列表 。

我试图将这些属性添加到我的班在各种组合,但仍没有运气:

[Serializable] 
[KnownType(typeof(List<BaseClass>))] 
[XmlInclude(typeof(List<BaseClass>))] 
[KnownType(typeof(BaseClass))] 
[XmlInclude(typeof(BaseClass))] 
public class DerivedClass : List<BaseClass> 
{ 
    /// ... 
} 

PS- Sheehs,我是说认为输入字段都在这个网站时髦的唯一一个?当我试图格式化时,事情会不断移动...:|无论我是否想要按照自己的意愿输入文字,这都是一个伟大的网站。

回答

4

你必须一个ServiceKnownTypeAttribute为您服务接口:

[ServiceKnownType(typeof(DerivedClass))] 
public interface IService 
{ 
    // Service declaration 
} 
+1

不确定这是否是最好的方法,因为这会将客户端代码紧密地耦合到服务接口。该服务只知道List ,并不认为它应该关心客户端如何发送它。假设另一个客户端想要派生DerivedClass,那么服务器需要添加另一个属性。不要认为这对软件维护非常有用。所有派生类的功能都与列表的包装类似,因此它可以操纵使用操作符/方法中构建的泛型List <>的列表元素。 –

+0

当您无法控制服务代码时,这是一个值得关注的问题。 –

0

有到register known types几种方法。但首先请研究有关DataContracts的articlestypes supported by the DataContractSerializer

请注意,您没有在DerivedClassBaseClass上添加DataContract属性。尽管标记为Serializable属性的类是有效的,并且可以在WSDL中公开,但DataContractAttibute具有专为互操作性设计的序列化规则,并且它是WCF的首选序列化机制。

如果您决定将数据合同上注册已知类型那么这应该足够:

[DataContract]  
public class DerivedClass : List<BaseClass> 
{ 
    /// ... 
} 

[DataContract] 
[KnownType(typeof(DerivedClass))] 
public clas BaseClass 
{ 
    //Add the DataMemberAttribute to the properties you want serialized. 
} 

如果你想在您添加的ServiceContractServiceKnownType属性的服务合同级别注册的已知类型。

+0

BaseClass的定义与您注意到的一样。客户端只需从该类中派生出来,以利用泛型List <>操作符/方法;如果客户简单地采用了一种方法而不是一种方法,那么实施就会奏效;也就是说,如果客户没有从名单中派生出来,而是将其作为财产。但是这看起来很笨重。 服务是否有必要了解List 的派生实现?似乎没有,客户需要发送清单;客户端派生的clss应该隐藏在服务器上 –

+0

您不必在服务合同和数据合同级别添加它。一个就足够了。另一种方法是使用配置文件或使用KnownTypeAttbibute .ctor,该参数以参数形式返回IEnumerable已知类型的帮助程序方法的名称。无论如何,我看不到你的派生类的重点。它让你的设计更难理解,没有任何好处(可以从你的例子和评论中看到)。删除派生类并在服务操作中使用IList 或IEnumerable 。这样你就可以封装集合类型并拥有简单的可维护代码。 –

+0

派生类纯粹是在列表上运行,就是这样。只是帮手功能。就像在列表上运行的函数一样;例如,将列表的所有项目属性设置为给定某些条件的值,并根据列表计算一些值。基本上,所有的数据和操作都包含在DerivedClass中,而不是每次我们需要执行常见任务时都需要创建一个单独的“Helper”类。现在如果你说有两个类(Derived和Helper)是一个好设计,我不同意。 –