Подтвердить что ты не робот

Типы запросов в разных пространствах имен с одинаковым расположением в С#

Я начал писать интерфейс для API-интерфейсов FedEx webservice. У них есть 3 различных API, которые меня интересуют; Скорость, Корабль и Трек. Я генерирую служебные прокси с помощью SvcUtil.exe.

Различные конечные точки обслуживания определяются FedEx в своих файлах WSDL. Каждая конечная точка обслуживания имеет собственное пространство имен xml (например, http://fedex.com/ws/rate/v5 и http://fedex.com/ws/ship/v5)

Конечные точки службы используют довольно много одинаковых типов, таких как Адрес, Измерения, Вес, АутентификацияDetail, ClientDetail и т.д.

И вот в чем проблема: я могу одновременно предоставить все файлы WSDL для SvcUtil.exe, и обычно он объединяет любые одинаковые типы в один общий тип, но поскольку каждая из служб FedEx находится в их собственных пространства имен, и они обновляют эти типы в каждом файле WSDL под этим пространством имен, в результате чего я получаю адрес Address, Address1 и Address2 для каждого пространства имен.

Чтобы решить эту проблему, теперь я должен запускать каждый WSDL через svcutil отдельно и помещать их каждый в свое собственное пространство имен .NET(например, FedEx.Rate, FedEx.Ship, FedEx.Track). Проблема заключается в том, что теперь у меня есть отдельный тип адреса в каждом пространстве имен (Fedex.Rate.Address, FedEx.Ship.Address).

Это затрудняет обобщение кода, используемого между службами, например методом GetAuthenticationDetail() factory, поэтому мне не нужно повторять этот код в каждом месте, где я использую разные службы.

Есть ли способ в С# для принудительного использования FedEx.Rate.Address для FedEx.Ship.Address?

4b9b3361

Ответ 1

Если типы идентичны, и у вас есть контроль над исходными классами, вы можете определить

Ответ 2

Итак, вот как я реализовал неявные операторы преобразования, используя отражение. SvcUtil создает частичные классы, поэтому я добавил неявный оператор преобразования для каждого направления преобразования, поэтому в код клиента вы можете просто набрать Type1 = Type2.

В этом фрагменте WebAuthenticationCredentials является свойством WebAuthenticationDetails, поэтому, итерации свойств исходного объекта, если типы arent одинаковы (встроенные), он проверяет имя типов (без пространства имен) и рекурсивно вызывает функцию копирования с этими свойствами.

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);
        }
    }
}

Ответ 3

вы можете использовать перегрузку оператора, создав собственную реализацию адреса или используя один из стабильных типов как свойство

один пример: Address1 и Address2 ниже будут вашим Rate.Address и Ship.Address соответственно

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);
    }
}

Изменить: подход такой же, как и сообщение выше, реализация находится в отдельном классе, который все

Ответ 4

Являются ли эти сгенерированные классы определенными как "частичные"? Если это так, вы можете расширить их в другом файле и извлечь интерфейс и позволить ему реализовать все классы адресов.