Ошибка при сериализации объекта CLR для использования в службе WCF - PullRequest
2 голосов
/ 05 февраля 2011

Я написал объект пользовательского исключения.Причина в том, что я хочу отслеживать дополнительную информацию при возникновении ошибки.Мой объект CLR определен следующим образом:

public class MyException : Exception
{
  public override string StackTrace
  {
    get { return base.StackTrace; }
  }
  private readonly string stackTrace;

  public override string Message
  {
    get { return base.Message; }
  }
  private readonly string message;

  public string Element
  {
    get { return element; }
  }
  private readonly string element;

  public string ErrorType
  {
    get { return errorType; }
  }
  private readonly string errorType;

  public string Misc
  {
    get { return misc; }
  }
  private readonly string misc;

  #endregion Properties

  #region Constructors

  public MyException() 
  {}

  public MyException(string message) : base(message)
  { }

  public MyException(string message, Exception inner) : base(message, inner)
  { }

  public MyException(string message, string stackTrace) : base()
  {
    this.message = message;
    this.stackTrace = stackTrace;
  }

  public MyException(string message, string stackTrace, string element, string errorType, string misc) : base()
  {
    this.message = message;
    this.stackTrace = stackTrace;
    this.element = element;
    this.errorType = errorType;
    this.misc = misc;
  }   

  protected MyException(SerializationInfo info, StreamingContext context) : base(info, context)
  {
    element = info.GetString("element");
    errorType = info.GetString("errorType");
    misc = info.GetString("misc");
  }

  public override void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    base.GetObjectData(info, context);
    info.AddValue("element", element);
    info.AddValue("errorType", errorType);
    info.AddValue("misc", misc);
  }
}

Я создал копию этого пользовательского исключения в приложении WP7.Единственная разница в том, что у меня нет определенного метода GetObjectData или конструктора с заданным SerializationInfo.Если я запускаю приложение как есть, я получаю сообщение об ошибке:

Тип «My.MyException» не может быть сериализован.Попробуйте пометить его атрибутом DataContractAttribute и пометить все его элементы, которые вы хотите сериализовать, атрибутом DataMemberAttribute.Если тип является коллекцией, попробуйте пометить его с помощью CollectionDataContractAttribute.

Если я добавлю атрибуты DataContract / DataMember к классу и его соответствующим членам на стороне сервера, я получу сообщение об ошибке, которое говорит:: Тип не может быть ISerializable и иметь атрибут DataContractAttribute.

Как мне сериализовать MyException, чтобы я мог передать его экземпляр моей службе WCF.Обратите внимание, я хочу использовать свой сервис из приложения Android.Из-за этого я не хочу делать что-то слишком ориентированное на Microsoft.Это было моим страхом при работе с DataContract / DataMember.

Большое спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 05 февраля 2011

Вам необходимо добавить [Serializable] в ваш пользовательский класс. Это то, что ваша первая ошибка, скорее всего, говорит вам, что эта вещь должна быть сериализуемым, хотя он говорит вам использовать предпочтительный способ WCF (использовать DataContract).

Нельзя смешивать интерфейсы сериализации (DataContract AND ISerializable), о чем говорит вторая ошибка. Exception уже реализует ISerializable, и WCF будет поддерживать это. Похоже, из вашего кода вы уже добавили некоторые методы для этого (те, что с SerializationInfo).

Как сказал Марк, в использовании DataContract нет ничего слишком ориентированного на .NET, он настолько же независим от платформы, когда речь идет о потреблении на стороне клиента.

0 голосов
/ 05 февраля 2011

Нет ничего страшного в DataMember и т. Д .; они хорошо переводятся в стандартные концепции SOAP. Но исключения: меньше. Для чистого WCF вы должны рассматривать ошибки , а не необработанные исключения, но в случае general я бы вместо этого возвратил (как результат моей операции) объект, который необязательно включает информацию об ожидаемом неудачи. Неожиданные сбои должны быть оставлены на сервере, и должен быть возвращен общий результат «упс».

Например, вы можете просто получить что-то вроде:

[DataContract]
public class FooResult {
    [DataMember]
    public string Error {get;set;}
    [DataMember]
    public SomeType Result {get;set;}
}

, где вызывающий должен ожидать Error XOR a Result. Также обратите внимание, что без атрибутов DataContract / DataMember есть вероятность, что сериализатор действует как сериализатор field , что вам действительно не нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...