在倾向于向下倾斜(见[my original post])并制作[deep copies]后,我发现[this eponymous article]在C ++中提出了如何处理问题的建议。我兴奋地用C#实现了如下:
public partial class User
{
virtual public Employer GetEmployer() { return null; }
...
}
public partial class Employer
{
public override Employer GetEmployer() { return this; }
...
}
然后我就这样使用了:
User u = GetUser();
Employer e = u.GetEmployer();
然而(我想,毫不奇怪),永远不会调用覆盖并返回null。
我试图解决的问题是我收集的一个非常常见的用例:我得到一些我需要存储的数据,但它不完整。后来我获得了更多的数据,并用它来改进(低估)我对这个世界的理解。
在这种特殊情况下,我从使用我网站的人那里得到一个电子邮件地址,所以我知道他们是User
,但总的来说我对此不了解。之后(当他们填写表格时),我知道他们实际上是Employer
,所以我需要低估我的User
。
这里的正确方法是什么?
答案 0 :(得分:1)
我回答了你以前的一个问题。你正试图解决一些无法解决的问题。这里的解决方案是不使用继承。为什么因为继承是is a
关系。所以如果你有:
public class User { }
public class Employee : User { }
您已此关系Employeee is User
但您没有反向关系User is Employee
。但是,从User
到Employee
进行投射,您要做的就是这样做。 User
的实例无法转换为Employee
(除了我之前回答中提到的情况 - 但您没有这种情况)。
使用这种方法,你将以面向对象的方式解决它,而不需要继承转换或其他任何东西。
public class User
{
public virtual EmployeeData { get; set; }
}
public class EmployeeData { }
该方法会将您的设计从is a
更改为has a
关系。在这种情况下,EmployeeData
是以1 - 0..1关系映射的单独实体(这将导致数据库中的两个表)。如果您对User
和EmployeeData
都存储在同一个表中的事实感到满意,也可以使用1 - 1关系或ComplexType。
答案 1 :(得分:0)
您的示例中唯一缺少的部分是雇主不会从用户继承。
将您的声明更改为:
public partial class Employer : User
{
// ...
}
你应该好好去。我不确定我会走这条路。我可能只是使用as
关键字来安全地进行投射:
var user = GetUser();
var employer = user as Employer;
// if the cast failed, employer will be null
if(employer != null)
{
// Work with employer
}
答案 2 :(得分:0)
您应该关注State Pattern:
这是一种对象在运行时部分更改其类型的简洁方法。
然后,您可以与Prototype Pattern混合搭配:
[使用]一个原型实例,克隆它以生成新对象。
你可以得到这样的东西:
// State pattern: public "wrapper"
public class User {
UserState state = UserState.CreateUser();
public void SetIsEmployer ()
{
// Use UserState.IsEmployer() method to transition to the
// Employer state
state = state.IsEmployer ();
}
public User Employer {
get {return state.Employer.User;}
}
}
// State pattern: User state
internal class UserState {
// protected so that only CreateUser() can create instances.
protected UserState ()
{
}
public User User {
get {/* TODO */}
}
public virtual UserState Employer {
get {return null;}
}
// Creates a default prototype instance
public static UserState CreateUser ()
{
return new UserState ();
}
// Prototype-ish method; creates an EmployerState instance
public virtual UserState IsEmployer ()
{
return new EmployerState (/* data to copy...*/);
}
}
// State pattern: Employer state
class EmployerState : UserState {
internal EmployeeState ()
{
}
public override UserState Employer {
get {return this;}
}
}
如果您的公共User
类型需要更多“状态转换”,则只需在UserState
类型上提供更多类(每个状态一个)和prototype-ish方法以创建适当的目标状态类型。 User.state
始终是User
的当前状态。此设置允许您在运行时更改实例的表观运行时类型。