通用ServiceContracts和String.Format样式名称

时间:2010-07-22 18:32:00

标签: c# wcf generics serialization xsd

我知道格式化的DataContract名称,如下所述:http://msdn.microsoft.com/en-us/library/ms731045.aspx(自定义底部附近的通用类型的数据合约名称)。

示例:

[DataContract( Name = "SearchCriteriaFor{0}", Namespace = "http://schema.mycompany.com/MyProject/" )]
public class SearchCriteria<T> { ...

这会导致SearchCriteria<Employee>成为服务生成的XSD中的<xs:complexType name="SearchCriteriaForEmployee">。这看起来比SearchCriteriaOfEmployeeWkD50_Xf(通用+“Of”+类型+哈希)好很多。

我也想为ServiceContracts做这件事。不幸的是,使用{0}语法不起作用(大括号被转义并且零保持字面值)。我没有找到任何如何做到这一点的例子,但我希望因为它适用于DataContract,它也适用于ServiceContract。 有没有办法将类型参数包含在ServiceContract的自定义序列化名称中?

然而,在写这篇文章时,我发现即使默认命名实现也是如此,包括类型名称在内,甚至可能根本不需要ServiceContract。 为通用ServiceContract指定固定名称是否可以接受?我尝试了它并且它似乎正确生成了XSD,但是我是否必须担心由于此而导致的任何未来冲突?这是一个内部系统,我可以保证不会对任何可用作泛型类型参数的对象发生任何名称/命名空间冲突。

例如,如果我有IDataStore<T>,是否有任何问题:

[ServiceContract( Name = "DataStore", Namespace = "http://schema.mycompany.com/MyProject/" )]
public interface IDataStore<T> where T : MyBaseObject
{ IList<T> FindAll(); }

会导致生成的XSD显示http://schema.mycompany.com/MyProject/DataStore/FindAll而不是http://schema.mycompany.com/MyProject/IDataStoreOf_Employee/FindAll

这里有很多漫无边际的问题,所以真正的问题在上面以粗体显示。

1 个答案:

答案 0 :(得分:0)

不,无法将类型参数作为自定义序列化名称的一部分包含在内。使用Reflector,您可以在System.ServiceModel.Description.NamingHelper.GetContractName中找到创建名称的代码。它看起来像这样:

internal static XmlQualifiedName GetContractName(Type contractType, string name, string ns)
{
    XmlName name2 = new XmlName(name ?? TypeName(contractType));

TypeName函数具有为通用类型和数组类型创建名称的逻辑,但如果在合同中提供名称,它将只使用该名称。

我不建议为通用合约使用固定名称,但它可能有效。由于它是通用的,我假设您有多个实例,IDataStore<Foo>IDataStore<Bar>将具有相同的完全限定名称,但具有不同类型的操作。只要没有任何东西同时看到合同的两个版本你应该没问题,但如果有什么确实同时看到它们可能会混淆。

您能为每个服务创建通用接口的具体子类吗?您可以声明类似的内容:

[ServiceContract(Name = "EmployeeDataStore", Namespace = "http://schema.mycompany.com/MyProject/")]
public interface IEmployeeDataStore : IDataStore<Employee> { }

让您的服务类型实现该界面,而不仅仅是IDataStore<Employee>。然后,您可以为每种类型显式设置名称。

相关问题