visual puede programacion nombres nombre métodos miembros indicadores espacios espacio error distribuidos directamente contener como codigos clases campos biblioteca basicos c# .net web-services types coerce

puede - Tipos de coerción en diferentes espacios de nombres con diseño idéntico en C#



espacios de nombres visual basic (4)

Empecé a escribir una interfaz para las API de servicios web de FedEx. Tienen 3 API diferentes que me interesan; Tasa, envío y seguimiento. Estoy generando los proxies de servicio con SvcUtil.exe.

Los diferentes puntos finales del servicio son cada uno especificado por FedEx en sus propios archivos WSDL. Cada extremo del servicio tiene su propio espacio de nombre xml (por ejemplo, http://fedex.com/ws/rate/v5 y http://fedex.com/ws/ship/v5 )

Los puntos finales de servicio usan bastantes tipos idénticos como Dirección, Mediciones, Peso, Detalle de autenticación, Detalle de cliente, etc.

Y aquí es donde reside el problema, puedo proporcionar todos los archivos WSDL al mismo tiempo a SvcUtil.exe y normalmente combinaría cualquier tipo idéntico en un único tipo compartido, pero como cada uno de los servicios de FedEx está en su propio espacio de nombres, y ellos redeclaran estos tipos en cada archivo WSDL bajo ese espacio de nombre con el que termino, en cambio, es una Dirección, una Dirección1 y una Dirección una para cada espacio de nombres.

Para resolver ese problema, lo que hago ahora es ejecutar cada WSDL a través de svcutil por separado y ponerlos cada uno en su propio espacio de nombres .NET (por ejemplo, FedEx.Rate, FedEx.Ship, FedEx.Track). El problema con esto es que ahora tengo un tipo de dirección distinto en cada espacio de nombre (Fedex.Rate.Address, FedEx.Ship.Address).

Esto hace que sea difícil generalizar el código utilizado entre los servicios, como el método de fábrica GetAuthenticationDetail (), por lo que no tengo que repetir ese código en cada lugar donde utilizo los diferentes servicios.

¿Hay alguna manera en C # de obligar FedEx.Rate.Address a FedEx.Ship.Address?


¿Son esas clases generadas definidas como "parciales"? Si es así, podría extenderlos en un archivo diferente y extraer una interfaz y dejar que sea implementada por todas las clases de direcciones.


podría usar la sobrecarga del operador creando su propia implementación de Dirección o usar uno de los tipos estables como propiedad

un ejemplo: Address1 y Address2 a continuación serían su Rate.Address y Ship.Address respectivamente

class Address1 { public string name = "Address1"; } class Address2 { public string name = "Address2"; } class GenericAddress { public string name = "GenericAddress"; public static implicit operator GenericAddress(Address1 a) { GenericAddress p = new GenericAddress(); p.name = a.name; return p; } public static implicit operator GenericAddress(Address2 a) { GenericAddress p = new GenericAddress(); p.name = a.name; return p; } } class Program { static void Main(string[] args) { PrintName(new Address1());//prints address1 PrintName(new Address2());//prints address2 } static void PrintName(GenericAddress a) { Console.WriteLine(a.name); } }

Editar: el enfoque es el mismo que el anterior, la implementación está en una clase separada, eso es todo


Si los tipos son idénticos y usted tiene control sobre las clases fuente, puede definir un operador de conversión en la clase, y cualquier función que tome una Rate.Address tomará automáticamente una Ship.Address . Por ejemplo:

namespace Rate { class Address { string Street; string City; // ... public static implicit operator Ship.Address(Rate.Address addr) { Ship.Address ret; ret.Street = addr.Street; ret.City = addr.City; // ... return ret; } } }

Mi C # está un poco oxidado, pero espero que entiendas la idea.


Así que aquí es cómo implementé los operadores de conversión implícitos usando la reflexión. SvcUtil crea clases parciales, así que agregué un operador de conversión implícito para cada dirección de la conversión, así que en el código del cliente puede simplemente escribir Type1 = Type2 .

En este fragmento, WebAuthenticationCredentials es una propiedad de WebAuthenticationDetails por lo que al iterar las propiedades del objeto fuente si los tipos no son iguales (integrados) comprueba el nombre de los tipos (sin el espacio de nombres) y recurre a la función de copia con esas propiedades .

internal class ReflectionCopy { public static ToType Copy<ToType>(object from) where ToType : new() { return (ToType)Copy(typeof(ToType), from); } public static object Copy(Type totype, object from) { object to = Activator.CreateInstance(totype); PropertyInfo[] tpis = totype.GetProperties(BindingFlags.Public | BindingFlags.Instance); PropertyInfo[] fpis = from.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); // Go through each property on the "to" object Array.ForEach(tpis, tpi => { // Find a matching property by name on the "from" object PropertyInfo fpi = Array.Find(fpis, pi => pi.Name == tpi.Name); if (fpi != null) { // Do the source and destination have identical types (built-ins)? if (fpi.PropertyType == tpi.PropertyType) { // Transfer the value tpi.SetValue(to, fpi.GetValue(from, null), null); } else { // If type names are the same (ignoring namespace) copy them recursively if (fpi.PropertyType.Name == tpi.PropertyType.Name) tpi.SetValue(to, Copy(fpi.PropertyType, tpi.GetValue(from, null)), null); } } }); return to; } } namespace Rate { partial class WebAuthenticationDetail { public static implicit operator Ship.WebAuthenticationDetail(WebAuthenticationDetail from) { return ReflectionCopy.Copy<Ship.WebAuthenticationDetail>(from); } } partial class WebAuthenticationCredential { public static implicit operator Ship.WebAuthenticationCredential(WebAuthenticationCredential from) { return ReflectionCopy.Copy<Ship.WebAuthenticationCredential>(from); } } } namespace Ship { partial class WebAuthenticationDetail { public static implicit operator Rate.WebAuthenticationDetail(WebAuthenticationDetail from) { return ReflectionCopy.Copy<Rate.WebAuthenticationDetail>(from); } } partial class WebAuthenticationCredential { public static implicit operator Rate.WebAuthenticationCredential(WebAuthenticationCredential from) { return ReflectionCopy.Copy<Rate.WebAuthenticationCredential>(from); } } }