动态命名空间切换

Jam*_*ill 5 c# inheritance namespaces dynamic

我正在尝试为多个第三方 Web 服务放置一个 Web 服务包装器。为了解决这个问题,我们将与其中两个合作:

  1. 订单服务
  2. 地址服务

这两个服务在不同的命名空间中定义了相同的对象:

  1. OrderService.AuthenticationParameters
  2. 地址服务.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]";
    }
}
Run Code Online (Sandbox Code Playgroud)

我见过几个类似的问题。要么它们不适用于我的情况,要么我无法理解它们。

问题:我想要实现的目标可能吗?如果可能的话,我是否把事情复杂化了?

附加信息:最终,将有两个以上的服务共享这个公共对象。供应商为他们提供的每个功能分支提供单独的服务 URL。

Ada*_*rth 3

对此有很多解决方案。

  • 让您的服务代理类实现您自己的接口来公开方法,然后简单地使用反射来构建类型。
  • 将这两个服务包装在另一个类中,该类公开这些方法并引用这两个服务,然后只需提供一个切换参数来确定使用哪个。
  • 通过您自己的接口抽象服务的使用,并显式针对每个服务编写类(见下文)。

或者,如果您想玩动态和鸭子打字,这似乎可行:

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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住,它们都取决于具有相同签名的两个服务。

至于未来的其他服务,那就要看情况了。我从来没有真正遇到过需要动态地从一种服务切换到另一种服务,以在实现相同的事情时获得稍微不同的行为。

也许这应该从您的应用程序方面驱动?无需选择适合的服务,只需实现具有这种变化行为的类的两个版本 - 在其上放置一个公共接口,并决定在运行时使用哪个类然后,类本身将直接针对其中一项服务进行编码。

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,决定就牢牢地存在于您的客户端代码中,并且无需反射/动态类型:

IGetUsername usernameProvider = null;

if (UseProviderOne)
    usernameProvider = new UsernameViaProviderOne();

...
Run Code Online (Sandbox Code Playgroud)

为了强调这一点,您始终可以实现非常 SOA 并创建您的应用程序与之交互的另一个服务,该服务聚合了其他两个服务。那么至少您的客户端代码不会看到大量不同的服务,而只会与其中之一进行对话。