我正在尝试围绕几个第三方网络服务放置一个网络服务包装器。为了这个问题,我们将与其中两个一起工作:
- 订单服务
- 地址服务
这两个服务都在不同的命名空间中定义了相同的对象:
- OrderService.AuthenticationParameters
- 地址服务.AuthenticationParameters
我希望能够创建一个能够在 namespace 之间检测/切换的基类。例如:
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]";
}
}
我见过几个类似的问题。它们要么不适用于我的情况,要么我无法理解它们。
问题:我想要实现的目标是否可行?如果可能的话,我是不是把事情复杂化了?
附加信息:最终,将有两个以上的服务共享这个公共(public)对象。供应商为其提供的每个功能分支提供单独的服务 URL。
最佳答案
对此有很多解决方案。
- 让您的服务代理类实现您自己的接口(interface)来公开方法,然后简单地使用反射来构建一个类型。
- 将这两个服务包装在另一个公开方法并引用两个服务的类中,然后简单地提供一个切换参数来确定使用哪个。
- 通过您自己的接口(interface)对服务的使用进行抽象,并针对每个服务明确编码类(见下文)。
或者,如果您想玩动态和鸭子打字,这似乎可行:
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),并决定要您的类中的哪一个在运行时使用。然后将针对一个服务直接对该类本身进行编码。
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 并创建另一个服务,您的应用程序可以与之对话,该服务聚合了其他两个服务。那么至少您的客户端代码不会看到大量不同的服务,而只会与一个服务对话。
关于c# - 动态命名空间切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8008902/