2009-01-28 6 views
7

Necesito devolver un tipo complejo de un servicio web y he construido la clase MyComplexType que implementa la interfaz IMyComplexType. Ahora, en mi servicio web que tengo un método que debe devolver un objeto que implementa IMyComplexType así:¿Es posible devolver interfaces desde .net webservices o solo se pueden devolver clases concretas?

[WebMethod] 
public IMyComplexType GetMyComplexType() 
{ 
    IMyComplexType myCt = new MyComplexType(); 
    ... 
    return myCt; 
} 

Todo compila bien, pero cuando corro el servicio web se lanza una excepción de la siguiente manera:

System.NotSupportedException: Cannot serialize interface MyWebService.IMyComplexType. 

Es esto por diseño o me estoy perdiendo algo. ¿Puedo decorar mi clase o interfaz de alguna manera para permitir esto? ¿Tengo que eliminar todas las interfaces y solo trabajar con clases base concretas y tal vez abstractas para poder hacer esto con los servicios web .net?

Editar:

esta es la interfaz que estoy tratando de serializar:

public interface ICustomer 
{ 
    long Id {get; set;} 
    string Name {get; set;} 
    string EmailAddress {get; set;} 
} 

Respuesta

0

Ha sido un tiempo, pero creo que necesita sólo hacer que las interfaces se extienden ISerializable y todos deben ser buenos.

+0

Esto a su vez requiere que implemente la interfaz ISerializable en todas mis clases, mientras que esperaba poder serializar sin tener que hacer eso. Solo necesito las propiedades públicas. Eliminar las interfaces y simplemente usar las clases concretas funciona bien, pero ¿es una mejor práctica? – Fadeproof

0

No necesita implementar ISerializable - simplemente marcar la interfaz con el atributo Serializable debe ser todo lo que necesita hacer. Si desea implementar la interfaz, siga adelante; le dará un control detallado sobre cómo se serializa la interfaz. Pero me imagino que la implementación predeterminada debería estar bien. También verifique para asegurarse de que todos los miembros de la interfaz sean serializables también.

[Editar] Ni siquiera estaba pensando: no hay manera de que pueda implementar ISerializable ya que está intentando serializar una interfaz de todos modos. El lugar donde sería apropiado ISerializable sería en tipos personalizados que necesitan serialización personalizada expuesta por la interfaz.

+0

No se puede poner el atributo Serializable en las interfaces, solo en clases, enumeraciones, etc. Lo intenté pero no tuve suerte. ¿Algo más que sugieres? No tengo ninguna necesidad de serialización personalizada. Solo estoy tratando de exponer las cosas correctamente, a través de interfaces y tipos no concretos. ¿Es eso imposible con .net ws? – Fadeproof

+0

Parece que uno de los tipos en su interfaz no es serializable. ¿Puede editar su publicación y agregar el código para la interfaz? –

+0

Ok. Se agregó la interfaz. ¿Hay alguna manera de hacerlo sin implementar ISerializable ya que solo quiero que se serialice tal como está y sin necesidad de personalización? – Fadeproof

2

La respuesta breve es no, no puede devolver una interfaz a través de un servicio web.

La respuesta larga es que puede obtener el tipo de comportamiento que desea, pero es un poco raro. La solución es usar serialización binaria. Por lo tanto, serializa su tipo en bytes, haga que el método web devuelva una serie de bytes y luego, en el otro lado, deserializará los bytes a su tipo complejo.

Por ejemplo

[WebMethod] 
public byte[] GetMyComplexType() 
{ 

    IMyComplexType myCt = new MyComplexType(); 
    ... 

    MemoryStream stream = new MemoryStream(); 
    IFormatter fmt = new BinaryFormatter(); 
    fmt.Serialize(stream, myCt); 
    stream.Flush(); 
    byte[] bytes = stream.ToArray(); 
    stream.Close(); 

    return bytes; 
} 

Tendrá que convertir todo de nuevo en el otro extremo.

byte[] bytes = service.GetMyComplexType(); 
MemoryStream stream = new MemoryStream(bytes); 
BinaryFormatter fmt = new BinaryFomatter(); 
MyComplexType myCt = fmt.DeSerialize(stream); 

Probablemente pueda limpiar la deserialización creando un método genérico. Debo agregar que necesitará asegurarse de que puede hacer referencia al tipo complejo en el cliente.

Alternativamente, si son sus interfaces, entonces podría convertirlas en clases abstractas. Sin embargo, esto no funcionará si desea que la clase implemente múltiples interfaces (o ya hereda de otra clase) ya que solo puede heredar una clase. Si necesita un comportamiento polimórfico en el cliente, deberá usar el atributo XmlInclude.

Cuestiones relacionadas