WCF上DataContract和层次结构的问题

时间:2011-07-26 19:39:32

标签: wcf c#-4.0 datacontract

我的wcf项目中有一个对象有问题。 我可以说这个对象:

[DataContract(Name="ClassA")]
public class Person{
   //---attributes---
}

[DataContract(Name="ClassB")]
public class Men : Person{
  //---attributes---
}

另一方面,ClassB是ClassA的孩子。 然后我有一个帖子的方法:

[OperationContract]
[WebInvoke(UriTemplate= "Person", ResponseFormat = WebMessageFormat.Json, Method= "POST")]
public string PostPerson(Person person) {
    if(person is Men){
       //code...
    }
}

事情就是我收到了这个人(在另一方面,他们将我们作为一个ClassB发送)但是这个人是男人返回虚假的..为什么?

2 个答案:

答案 0 :(得分:1)

您需要将[ServiceKnownType(typeof(Men))]属性添加到PostPerson方法。

答案 1 :(得分:0)

正如Ryan Gross所提到的,你需要男人成为一个已知的类型。 Here's a similar question/answer here on SO.链接文章中未提及的一个选项是KnownType attribute。这是我过去使用的代码示例。前提条件是此类是所有数据协定的基类,并且所有数据协定都在同一个程序集中:

/// <summary>
///   Base class for all data contracts.
/// </summary>
[DataContract(Name = "Base", Namespace = "your namespace")]
[KnownType("GetKnownTypes")]
public class BaseDC : IExtensibleDataObject
{
  #region Constants and Fields

  /// <summary>
  ///   Instance used to control access to the known types list.
  /// </summary>
  private static readonly object _knownTypesLock = new object();

  /// <summary>
  ///   Classes derived from this class.  Needed to ensure proper functioning of the WCF data
  ///   constract serializer.
  /// </summary>
  private static List<Type> _knownTypes;

  #endregion

  #region Properties

  /// <summary>
  ///   Gets or sets an <c>ExtensionDataObject</c> that contains data that is not recognized as belonging to the
  ///   data contract.
  /// </summary>
  public ExtensionDataObject ExtensionData { get; set; }

  #endregion

  #region Public Methods

  /// <summary>
  ///   Enumerates the types in the assembly containing <c>BaseDC</c> that derive from <c>BaseDC</c>.
  /// </summary>
  /// <returns>List of <c>BaseDC</c>-derived types.</returns>
  [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
    Justification = "Not appropriate for a property.")]
  public static IEnumerable<Type> GetKnownTypes()
  {
    lock (_knownTypesLock)
    {
      if (_knownTypes == null)
      {
        _knownTypes = new List<Type>();
        Assembly contractsAssembly = Assembly.GetAssembly(typeof(BaseDC));
        Type[] assemblyTypes = contractsAssembly.GetTypes();
        foreach (Type assemblyType in assemblyTypes)
        {
          if (assemblyType.IsClass && !assemblyType.IsGenericType)
          {
            if (assemblyType.IsSubclassOf(typeof(BaseDC)))
            {
              _knownTypes.Add(assemblyType);
            }
          }
        }

        _knownTypes.Add(typeof(BaseDC));
      }

      return _knownTypes;
    }
  }

  #endregion
}