动态命名空间切换

时间:2011-11-04 12:01:40

标签: c# inheritance dynamic namespaces

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

  1. OrderService
  2. AddressService
  3. 这两个服务都具有在不同名称空间中定义的相同对象:

    1. OrderService.AuthenticationParameters
    2. AddressService.AuthenticationParameters
    3. 我希望能够创建一个能够在名称空间之间检测/切换的基类。例如:

      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 个答案:

答案 0 :(得分: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";
        }
    }
}

请记住,他们都依赖于具有相同签名的两项服务。

至于未来的其他服务,实际上取决于。我从来没有真正遇到过从一个服务动态切换到另一个服务的需要,以便在实现同样的事情时获得稍微不同的行为。

也许这应该来自你的应用程序?而不是选择适合的服务,只需实现具有这种变化行为的类的两个版本 - 在其上放置一个通用接口,并决定 您的 类中的哪一个在运行时使用。然后,类本身将直接针对一个服务进​​行编码。

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并创建另一项服务,您的应用会与之交谈,从而聚合其他两项服​​务。然后,至少你的客户端代码没有看到大量不同的服务,只与一个人进行对话。

答案 1 :(得分:0)

嗯,我唯一能想到的就是使用反射来创建对象。问题是你必须再次使用反射来设置属性,调用方法等,因为我猜你没有共享接口。虽然它的大量工作可能会降低性能,但它确实可以解决问题。  查看带有ActivatorCreateInstance,您可以传递完整的合格类名称并创建实例。 然后,使用此新创建对象的类型,您可以搜索要修改的属性。

答案 2 :(得分:-2)

您可以使用#if。

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

但是你无法改变运行时间,因为它适用于编译时。

注意:不是一个好的编程习惯。但这存在。