Динамическое переключение пространства имен - PullRequest
4 голосов
/ 04 ноября 2011

Я пытаюсь поместить оболочку веб-службы в несколько сторонних веб-служб. Ради этого вопроса мы будем работать с двумя из них:

  1. OrderService
  2. AddressService

Обе эти службы имеют один и тот же объект, определенный в разных пространствах имен:

  1. OrderService.AuthenticationParameters
  2. AddressService.AuthenticationParameters

Я надеялся создать единый базовый класс, который сможет обнаруживать / переключаться между пространствами имен. Например:

public abstract class BaseLogic
{
    internal BaseLogic()
    {
        /* Initialize authParams */

        //Switch out / detect namespace here
        this.authParams = new OrderService.AuthenticationParameters();
        this.authParams.accountName = "[MyAccountName]";
        this.authParams.userName = "[MyUserName]";
        this.authParams.password = "[MyPassword]";
    }
}

Я видел несколько похожих вопросов. Либо они не относятся к моей ситуации, либо я не способен их понять.

Вопрос: Возможно ли то, что я пытаюсь достичь? Если это возможно, я слишком усложняю?

Дополнительная информация: В конечном счете, будет более двух служб, которые совместно используют этот общий объект. Поставщик предоставляет отдельный URL-адрес службы для каждой ветви функциональности, которую он предоставляет.

Ответы [ 3 ]

3 голосов
/ 04 ноября 2011

Есть довольно много решений для этого.

  • Пусть ваши прокси-классы службы реализуют ваш собственный интерфейс для предоставления методов, а затем просто используют отражение для создания типа.
  • Оберните обе службы в другой класс, который предоставляет методы и имеет ссылку на обе службы, а затем просто укажите аргумент переключения, чтобы определить, какие из них использовать.
  • Аннотацияиспользовать службу через собственный интерфейс и иметь классы, явно закодированные для каждой службы (см. ниже).

Или, если вы хотите поиграть с динамической и утиной печатью, это, похоже, сработает:

namespace ConsoleApplication42
{
    class Program
    {
        static void Main(string[] args)
        {
            Type t1 = Type.GetType("ProviderOne.AuthService");

            dynamic service = Activator.CreateInstance(t1);

            Console.WriteLine(service.GetUsername());

            Type t2 = Type.GetType("ProviderTwo.AuthService");

            service = Activator.CreateInstance(t2);
            Console.WriteLine(service.GetUsername());

            Console.Read();
        }
    }
}

namespace ProviderOne
{
    public class AuthService
    {
        public string GetUsername()
        {
            return "Adam";
        }
    }
}

namespace ProviderTwo
{
    public class AuthService
    {
        public string GetUsername()
        {
            return "Houldsworth";
        }
    }
}

Имейте в виду, что все они зависят от обеих служб, имеющих одинаковую подпись.

Что касается других служб в будущем, то это действительно зависит.Я никогда не сталкивался с необходимостью динамического переключения с одного сервиса на другой, чтобы получить немного другое поведение при достижении одного и того же.

Возможно, это должно быть направлено со стороны вашего приложения?Вместо того, чтобы выбрать службу, подходящую для этого, просто реализуйте две версии класса с таким изменяющимся поведением - установите общий интерфейс для него и решите, какой из ваших классов использовать вво время выполнения.Затем сам класс будет закодирован непосредственно против одного сервисов.

interface IGetUsername
{
    string GetUsername();
}

class UsernameViaProviderOne : IGetUsername
{
    public string GetUsername()
    {
        return new ProviderOne.AuthService().GetUsername();
    }
}

class UsernameViaProviderTwo : IGetUsername
{
    public string GetUsername()
    {
        return new ProviderTwo.AuthService().GetUsername();
    }
}

Тогда решение полностью закреплено в вашем клиентском коде и устраняет необходимость в рефлексии / динамической типизации:

IGetUsername usernameProvider = null;

if (UseProviderOne)
    usernameProvider = new UsernameViaProviderOne();

...

Чтобы разобраться в этом вопросе, вы всегда можете получить SOA и создать еще один сервис, с которым ваше приложение взаимодействует, объединяющий два других сервиса.Тогда, по крайней мере, ваш клиентский код не видит огромное количество различных сервисов и общается только с одним.

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

Вы можете использовать # if.

#if true
using MyService.X;
using x=MyService.A;
#endif
#if false
using MyService2.X;
using x=MyService.B;
#endif

Но вы не можете изменить время выполнения, так как оно работает во время компиляции.

Примечание: не очень хорошая практика программирования,Но это существует.

0 голосов
/ 04 ноября 2011

Хм, единственное, о чем я могу думать, - это использовать отражение для создания объекта.Проблема в том, что вам нужно снова использовать отражение, чтобы установить свойства, вызывать методы и т. Д., Потому что, я думаю, у вас нет общего интерфейса.Хотя это много работы, и это может снизить производительность, это делает свое дело.Взгляните на Activator с CreateInstance , вы можете передать полное имя класса и создать свой экземпляр.Затем, используя тип этого нового созданного объекта, вы можете искать свойства, которые вы хотите изменить.

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