![](/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.