2009-02-03 9 views
10

estoy teniendo un pequeño problema con los proxies de servicio WCF en el que el mensaje contiene List<string> como parámetro.¿Puedo detener mi generación WCF ArrayOfString en lugar de cadena [] o la lista <string>

Estoy utilizando el 'Agregar servicio de referencia' en Visual Studio para generar una referencia a mi servicio.

// portion of my web service message 
    public List<SubscribeInfo> Subscribe { get; set; } 
    public List<string> Unsubscribe { get; set; } 

Estas son las propiedades generadas en mi MsgIn para uno de mis métodos web. Se puede ver que solía ArrayOfString cuando estoy usando List<string>, y el otro lleva List<SubscribeInfo> - que coincide con mi C# objeto original anterior.

[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)] 
public System.Collections.Generic.List<DataAccess.MailingListWSReference.SubscribeInfo> Subscribe { 
    get { 
     return this.SubscribeField; 
    } 
    set { 
     if ((object.ReferenceEquals(this.SubscribeField, value) != true)) { 
      this.SubscribeField = value; 
      this.RaisePropertyChanged("Subscribe"); 
     } 
    } 
} 

[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)] 
publicDataAccess.MailingListWSReference.ArrayOfString Unsubscribe { 
    get { 
     return this.UnsubscribeField; 
    } 
    set { 
     if ((object.ReferenceEquals(this.UnsubscribeField, value) != true)) { 
      this.UnsubscribeField = value; 
      this.RaisePropertyChanged("Unsubscribe"); 
     } 
    } 
} 

La clase ArrayOfString generada se ve así. Esta es una clase generada en mi código, no es una clase .NET. En realidad, me generó una clase que hereda de List, pero no tuve la 'decencia' de crearme ningún constructor.

[System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")] 
    [System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfString", Namespace="http://www.example.com/", ItemName="string")] 
    [System.SerializableAttribute()] 
    public class ArrayOfString : System.Collections.Generic.List<string> { 
    } 

El problema es que a menudo crear mi mensaje como este:

client.UpdateMailingList(new UpdateMailingListMsgIn() 
{ 
    Email = model.Email, 
    Name = model.Name, 
    Source = Request.Url.ToString(), 
    Subscribe = subscribeTo.ToList(), 
    Unsubscribe = unsubscribeFrom.ToList() 
}); 

me gusta mucho el aspecto limpio esto me da.

Ahora para el problema real:

I Cant asignar un List<string> a la propiedad Unsubscribe que es un ArrayOfString - a pesar de que hereda de la lista. De hecho, parece que no puedo encontrar CUALQUIER forma de asignarlo sin declaraciones adicionales.

He intentado lo siguiente:

  • new ArrayOfString(unsubscribeFrom.ToList()) - este constructor no existe :-(
  • cambiar el tipo de la matriz utilizada por el generador de código - no funciona - siempre me da ArrayOfString
  • intenta convertir a List<string>ArrayOfString (!?) - falla con 'incapaz de lanzar', a pesar de que compila bien
  • crear new ArrayOfString() y luego AddRange(unsubscribeFrom.ToList()) - obras, pero no puedo hacer yo t todo en una sola declaración
  • crea una función de conversión ToArrayOfString(List<string>), que funciona pero no está tan limpia como yo quiero.

Esto solo hace esto para el hilo, que es molesto.

¿Echo de falta algo? ¿Hay alguna forma de decirle que no genere ArrayOfString, o algún otro truco para asignarlo?

Respuesta

7

Cualquier objeto .NET que implementa un método llamado "add" se puede inicializar como matrices o diccionarios.

Como ArrayOfString hace poner en práctica un método de "Añadir", puede inicializar así:

var a = new ArrayOfString { "string one", "string two" }; 

Pero, si realmente desea inicializarlo basado en otra colección, se puede escribir un método de extensión para ese :

public static class U 
{ 
    public static T To<T>(this IEnumerable<string> strings) 
     where T : IList<string>, new() 
    { 
     var newList = new T(); 
     foreach (var s in strings) 
      newList.Add(s); 
     return newList; 
    } 
} 

Uso:

client.UpdateMailingList(new UpdateMailingListMsgIn() 
{ 
    Email = model.Email, 
    Name = model.Name, 
    Source = Request.Url.ToString(), 
    Subscribe = subscribeTo.ToList(), 
    Unsubscribe = unsubscribeFrom.To<ArrayOfString>() 
}); 
1

Si está utilizando VS 2008 para consumir el servicio entonces no hay una solución fácil.

Haga clic en el botón "Avanzado ..." en el diálogo de proxy que se muestra cuando se agrega una referencia de servicio. En el menú desplegable Tipo de recopilación, puede seleccionar System.Generic.List. Los métodos que devuelven Lista ahora deberían funcionar correctamente.

(espero que esto es lo que estaba pidiendo, estoy un poco cansado y la pregunta era un poco difícil para mí leer.)

+1

¡Estoy cansado también! sigo escribiendo preguntas demasiado largas. lo siento si no estaba claro. ¡Creo que lo has entendido! desafortunadamente su sugerencia no funciona - ¡INSISTE en hacer una nueva clase de ArrayOfString para la cadena, lo que sea que elija 4! tal vez se confunde la cadena de pensamiento es un tipo de valor? –

+0

hmm. Tendría que probarlo. desafortunadamente mi horario de trabajo es un poco agitado hoy –

+0

Encontré que esto no funciona. – Abacus

3

prefiero no volver tipos genéricos a través de una frontera de servicio en el primer lugar. En su lugar, devuelva Anular suscripción como string[] y SubscriptionInfo como SubscriptionInfo[]. Si es necesario, una matriz se puede convertir fácilmente a una lista genérica en el cliente, de la siguiente manera:

Unsubscribe = new List<string>(unsubscribeFrom); 
Subscribe = new List<SubscriptionInfo>(subscribeTo); 
3

demasiado tarde, pero puede ayudar a las personas en el futuro ..

Utilice el svcutil e informe explícitamente a la línea de comandos util que desea que la clase proxy sea serializada por el XmlSerializer y no el DataContractSerializer (predeterminado). Aquí está la muestra:

svcutil /out:c:\Path\Proxy.cs /config:c:\Path\Proxy.config/asíncrono/serializador: XmlSerializer/espacio de nombres: *, YourNamespace http://www.domain.com/service/serviceURL.asmx

Tenga en cuenta que el servicio web es un servicio web ASP.NET ¿ok?

+0

¿Es esto esencialmente la diferencia entre una "referencia de servicio" y una "referencia web"? ¿Especifica la referencia de servicio usar DataContractSerializer, y la referencia web usa XmlSerializer? –

+0

De hecho, ayudó a la gente en el futuro, muchas gracias señor! –

Cuestiones relacionadas