【问题标题】:WCF With a interface and a generic modelWCF 带有接口和泛型模型
【发布时间】:2016-02-11 11:34:46
【问题描述】:

关于 WCF 中的接口和泛型有很多关于 SO 的问题,但我找不到一个与我有相同问题的问题。

我有一项合同服务:

[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
public interface IService : 
{
    [OperationContract]
    ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);
}

public interface ICollectionWrapper<TModel>
{
    int TotalCount { get; set; }
    IEnumerable<TModel> Items { get; set; }
}

[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
    [DataMember]
    public int TotalCount { get; set; }
    [DataMember]
    public IEnumerable<TModel> Items { get; set; }
}

public class CompanyDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OrganizationDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

它与ChannelFactory&lt;IService&gt; 一起使用,上面的代码效果很好。但现在我想在服务中添加另一个方法,它也返回ICollectionWrapper&lt;T&gt;

[OperationContract]
ICollectionWrapper<ICustomer> Search(ISearchQuery searchQuery);

所以我像注册另一个一样注册它:

[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
[ServiceKnownType(typeof(CollectionWrapper<ICustomer>))] // This line creates the error.
public interface IService : 
{
    [OperationContract]
    ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);

    [OperationContract] // New method.
    ICollectionWrapper<ICustomer> Search(ISearchQuery searchQuery);
}

[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
[KnownType(typeof(CustomerDto))] // New model.
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
    [DataMember]
    public int TotalCount { get; set; }
    [DataMember]
    public IEnumerable<TModel> Items { get; set; }
}

一旦我有两个ServiceKnownTypesCollectionWrapper,服务就会失败并出现以下错误:

底层连接已关闭:发生意外错误 一个接收。

还有内部异常:

一个现有的连接被远程主机强行关闭。

我可以在这两行代码之间切换(删除一行,添加另一行):

[ServiceKnownType(typeof(CollectionWrapper<ICustomer>))]

[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]

然后每个方法都起作用,但不能同时进行。知道如何让它工作吗?我不想使用具体的类。

这是我尝试过的(但失败了):

[ServiceKnownType(typeof(CollectionWrapper<object>))]

[ServiceKnownType(typeof(CollectionWrapper<>))]

我还尝试为 IAssociation 和 ICustomer 分配一个通用接口,但它也不起作用。

[ServiceKnownType(typeof(CollectionWrapper<ISomething>))]

它适用于 IEnumerable&lt;T&gt;IList&lt;T&gt; 但不适用于我的 ICollectionWrapper&lt;T&gt;

编辑:

ICustomerIAssociation(以及它们的实现)没有任何共同之处。它们不相互继承任何东西,也没有任何其他共同的依赖关系。

【问题讨论】:

  • 或许内部异常会给你一个更好的线索:Type WcfService1.CollectionWrapper1[WcfService1.ICustomer]' cannot be added to list of known types since another type WcfService1.CollectionWrapper1[WcfService1.IAssociation]' with the same data contract name' schemas.datacontract.org/2004/07/…' 已经存在。如果存在特定类型的不同集合 - 例如,List<Test>和 Test[],它们不能都添加为已知类型。考虑仅指定其中一种类型以添加​​到已知类型列表中。
  • 一种可能的解决方案是创建,例如,public class CustomerCollection : ICollectionWrapper&lt;ICustomer&gt;public class AssociationCollection : ICollectionWrapper&lt;IAssociation&gt;
  • @jstreet - 感谢您的建议。我已经编辑了我的问题并添加了内部异常。和你说的不一样。您的其他建议可能会起作用,但需要更多执行相同操作的模型,我想避免这样做。但这是一个很好的最后手段。
  • 嗯,你发布的内部异常也没有解释太多......也许除了类型冲突之外你还有其他问题。我提出的解决方案确实有效。但我认为这里真正的解决方案是你需要弄清楚你的类/接口层次结构。

标签: c# wcf generics interface


【解决方案1】:
[OperationContract]
ICollectionWrapper<ICustomer> Search(ISearchQuery searchQuery);

服务如何知道 ISearchQuery 参数存在哪些已知类型?

我认为您需要在服务定义中添加 [KnownType(typeof(SearchQuery))](或任何您的 ISearchQuery 实现)。

【讨论】:

  • 你说得对。但在这种情况下,我通过将 ISearchQuery 更改为字符串来尝试此操作。因此,即使这也是一个问题,也不是导致错误的原因。此外,只要我删除其他 ServiceKnownType,该方法本身就可以工作。
【解决方案2】:

经过大量研究,我无法找到一个好的解决方案,但我想我会发布我最终得到的解决方案(即使它没有按照我想要的方式解决它)

[ServiceContract]
[ServiceKnownType(typeof(CompanyDto>))]
[ServiceKnownType(typeof(CompanyDto>))]
[ServiceKnownType(typeof(CustomerDto))]
[ServiceKnownType(typeof(OrganizationDto))]
public interface IService : 
{
    [OperationContract] // Concrete type
    CollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);

    [OperationContract] // Concrete type
    CollectionWrapper<ICustomer> Search(ISearchQuery searchQuery);
}

通过使用具体类而不是接口来简单地解决它。这不是我真正想要的,但现在它解决了我的问题。

此处可能重复:

Generic return types with interface type params in WCF

【讨论】:

  • 我认为我没有将其标记为 asnwer,因为它并没有真正回答我原来的问题(使用没有具体类的泛型)。我希望那里有更好的答案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 2020-03-24
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多