动态命名空间切换

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

  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]"; } } 

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

问题:我正在努力实现的目标是什么? 如果有可能,我是否过于复杂化?

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

有很多解决方案。

  • 让您的服务代理类实现您自己的接口以公开方法,然后只使用reflection来构建类型。
  • 将这两个服务包装在另一个暴露方法的类中,并引用这两个服务,然后简单地提供一个切换参数来确定使用哪个。
  • 摘要通过您自己的接口使用服务,并明确地为每个服务编码类(见下文)。

或者如果你想玩动态和鸭子打字,这似乎工作:

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

然后决定坚定地在您的客户端代码中,并消除了对reflection/动态类型的需求:

 IGetUsername usernameProvider = null; if (UseProviderOne) usernameProvider = new UsernameViaProviderOne(); ... 

为了解决这个问题,你总是可以获得非常SOA并创建另一个服务,你的应用程序会与之聚合,以聚合其他两个服务。 那么至少你的客户端代码没有看到大量不同的服务,只能与一个人进行对话。

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

你可以使用#if。

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

但是你不能在运行时改变,因为它在编译时工作。

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