![](/img/trans.png)
[英]Using the same method to instantiate identical object from different namespaces
[英]C# When consuming two sets of “identical” classes from different namespaces, how do I avoid writing the same method(s) twice?
我有两个名称空间,每个名称空间中有三个类。这两组三个类 - 就我的目的而言 - 在名称和属性上是相同的,但每个集合都存在于它自己的名称空间中。
您可以猜测,此代码是从同一服务的两个实例自动生成的(一个用于生产,另一个用于UAT)。 每个实例可能在同一版本上,也可能不在同一版本上,但我关心的成员总是相同的。
例如:
namespace Domain.Uat //Auto-generated
{
public class LoginResult { }
public class ServiceSession { }
public class Service
{
public ServiceSession Session { get; set; }
public LoginResult Login(string username, string password);
}
}
namespace Domain.Prod //Auto-generated
{
public class LoginResult { }
public class ServiceSession { }
public class Service
{
public ServiceSession Session { get; set; }
public LoginResult Login(string username, string password);
}
}
我有一个登录服务的类,并做了很多其他的事情。 我希望能够从UI层选择UAT或Prod,所以我添加了一个名为“isUat”的bool参数给我 - 在这种情况下 - Login()方法。
我想避免编写两个几乎相同的Login()方法。 所以我在考虑这样的事情:
namespace Domain
{
public class DomainClass
{
private object MyService;
private object MyLoginResult;
private object MySession;
public void Login(string username, string password, bool isUat)
{
//New up the service here:
if (isUat)
MyService = new Domain.Uat.Service();
else
MyService = new Domain.Prod.Service();
//Do all the common stuff here
MyLoginResult = MyService.Login(username, password);
MySession = MyService.Session;
}
//(Lots of other methods that use MyService and MySession go here)
}
}
声明类型对象并向其投射是愚蠢的,但我认为它说明了我的一般方法。 我已经使用部分类和接口(“ILoginResult”,“IServiceSession”,“IService”等)以不同的方式工作,但它感觉很烦人。
是否存在针对此问题的最佳实践模式,还是我写了两个Login()方法?
UPDATE
我上面提到的部分类和接口方法的工作方式如下:
namespace Domain
{
public interface ILoginResult { }
public interface IServiceSession { }
public interface IService
{
public IServiceSession Session { get; set; }
public ILoginResult Login(string username, string password);
}
}
然后我添加一些代码(不是自动生成的)来扩展自动生成的类:
namespace Domain.Uat //Do the same for Domain.Prod
{
public partial class LoginResult : Domain.ILoginResult { }
public partial class ServiceSession : Domain.IServiceSession { }
public partial class Service : Domain.IService { } //Doesn't work, see below
}
然后我像这样修改我的DomainClass:
namespace Domain
{
public class DomainClass
{
private ILoginResult MyLoginResult;
private IServiceSession MyServiceSession;
private IService MyService;
public void Login(string username, string password, bool isUat)
{
//New up the service here
if (isUat)
MyService = new Domain.Uat.Service();
else
MyService = new Domain.Prod.Service();
//Common stuff here
MyLoginResult = MyService.Login(username, password);
MyServiceSession = MyService.ServiceSession;
}
//More members here
}
}
但是,这不起作用,因为Domain.Uat.Service实际上并不实现Domain.IService。 Domain.IService.ServiceSession获取设置IServiceSession,但Domain.Uat.Service实际上没有名为ServiceSession的IServiceSession属性。 LoginResult也是如此。
所以,现在在我的部分课程中,我不得不像这样实现新的具体成员:
namespace Domain.Uat //Do the same for Domain.Prod
{
public partial class LoginResult : Domain.ILoginResult { }
public partial class ServiceSession : Domain.IServiceSession { }
public partial class Service : Domain.IService
{
public Domain.IServiceSession Domain.IService.ServiceSession
{
get { return Session; }
set { Session = (Domain.Uat.ServiceSession)value; }
}
public Domain.ILoginResult Domain.IService.Login(string username, string password)
{
return Login(username, password);
}
}
}
我不喜欢这个,所以我尝试使用泛型来避免具体实现,如下所示:
namespace Domain
{
public interface ILoginResult { }
public interface IServiceSession { }
public interface IService<TLoginResult, TServiceSession>
where TLoginResult : ILoginResult
where TServiceSession : IServiceSession
{
public TServiceSession Session { get; set; }
public TLoginResult Login(string username, string password);
}
}
...导致我的Service类签名发生变化,如下所示:
namespace Domain.Uat //Do the same for Domain.Prod
{
public partial class LoginResult : Domain.ILoginResult { }
public partial class ServiceSession : Domain.IServiceSession { }
public partial class Service : Domain.IService<LoginResult, ServiceSession> { }
}
所以我避免了具体的实现,但是现在当我在DomainClass中使用服务时编译器中断了:
namespace Domain
{
public class DomainClass
{
private IService MyService;
private ILoginResult MyLoginResult;
private IServiceSession MySession;
public void Login(string username, string password, bool isUat)
{
//New up the service here:
if (isUat)
MyService = new Domain.Uat.Service(); //Compiler fail, can't cast
else
MyService = new Domain.Prod.Service(); //Compiler fail, can't cast
//Do all the common stuff here
MyLoginResult = MyService.Login(username, password);
MySession = MyService.Session;
}
//(Lots of other methods that use MyService and MySession go here)
}
}
我正在挖洞的感觉太深了,所以我退后一步,发布在Stack Overflow上!
PS协方差和逆变法对我的IService接口不起作用,因为一个成员是一个属性(是的,我需要能够在Session上获取和设置)。
我不认为为每个类使用一个接口是不好的。 然后改变为这样。
private ILoginResult MyLoginResult
然后为domainclass创建一个构造函数并传递uat并在构造函数中实例化您的属性。
然后登录方法或任何其他方法将不需要if语句
如果无法控制生成的代码的接口,则可以为从公共接口/抽象类继承的每个服务创建包装器。
public class WrappedUatService : IService {
private Domain.Uat.Service _service;
public override ILoginResult Login() {
ILoginResult result = new WrappedLoginResult(_service.Login());
...
}
}
public class WrappedProdService : IService {
private Domain.Prod.Service _service;
public override ILoginResult Login() {
ILoginResult result = new WrappedLoginResult(_service.Login());
...
}
}
这是一些额外的代码,但你不能将它们视为等效的,因为它们碰巧有相同签名的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.