我有一个电话号码通知模型(用户通过与他们的帐户关联的电话号码获得紧急情况的通知,他们可以设置这些电话号码的调用顺序)。大多数情况下,模型的电话号码部分是必需的,但在创建新用户时会有一个特殊情况,我们不想强迫它。
我做了一个非常简单的子对象UserCreationPhoneNotificationModel,它继承自上面描述的UserPhoneNotificationModel。还有其他一些小的变化,但是这里的相关变化覆盖了PhoneNumber字段,因此不再需要它。
在父模型中它是
[Required]
public virtual string PhoneNumber { get; set; }
在儿童模特中,它只是
public override string PhoneNumber { get; set; }
我认为这可以解决问题,但显然不是。我认为问题是RequiredAttribute会对它有Inherited = true,但事实并非如此,我不完全确定为什么它会被继承到子类中。
我做了双重检查以确保,并且从父级字段中删除Required也使得子类中的字段不是必需的,所以它绝对是某种继承的东西。
答案 0 :(得分:2)
当您建模的关系不适合时,使用继承来共享行为可能会有问题。您通常不会从使用继承来共享ViewModel之间的行为中获得任何好处,而您可以(并且,在您的情况下,执行)遇到问题。
最好的办法是为每个用例使用不同的模型类。如果您确实需要在ViewModel之间共享行为,则可以使用合成。
答案 1 :(得分:1)
可以通过隐藏现有同一个新属性来实现。 因此,如果该属性在父类中是这样的:
[Required]
public virtual string PhoneNumber { get; set; }
您可以像下面这样在子类中定义新属性:
public new string PhoneNumber { get; set; }
这将在子类中隐藏PhoneNumber属性及其属性。现在,您可以使用其他任何属性。例如,您可以向子类中的属性添加[PhoneNumber]
属性。
答案 2 :(得分:0)
以下示例可能会对您有所帮助。
public class SigninModel
{
[Required]
[EmailAddress]
public virtual string email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string password { get; set; }
}
这是Signin模型,我已经继承了另一个模型,但电子邮件不需要它的代码如下:
public class ExternalLoginModel : SigninModel
{
public override string email { get; set; }
public string LoginProvider { get; set; }
public string ProviderKey { get; set; }
}
我在另一个模型中覆盖了电子邮件属性
答案 3 :(得分:0)
不继承属性是没有意义的。
覆盖时删除[Required]
属性基本上违反了 LSP 。
如果
NotRequiredDerived
是RequiredBase
的子类型,则RequiredBase
类型的对象可以替换为NotRequiredDerived
类型的对象(即RequiredBase
类型的对象{1}}可以替换为子类型NotRequiredDerived
的任何对象,而不会改变程序的任何所需属性。
用简单的代码表示:
var requiredPhoneNumber = new RequiredBase() { PhoneNumber = "123456789" };
HandleRequiredBaseObject(requiredPhoneNumber); //Works
var optionalPhoneNumber = new NotRequiredDerived() { PhoneNumber = null };
HandleRequiredBaseObject(optionalPhoneNumber); //Fails
HandleRequiredBaseObject(RequiredBase obj)
固有地假定PhoneNumber
是必需的(根据RequiredBase
类的定义);并且它不期望收到缺少此约束的派生对象!这将导致运行时异常。
不违反LSP的唯一方法是确保在派生类上不违反[Required]
约束;这意味着首先尝试删除[Required]
注释是没有意义的。
我可以想到一个理论的情况,其中不继承该属性是有意义的:如果属性扩展有效选项的范围,而不是限制它。
假设我们创建了一个类PositiveNumber
和一个将其设置为也允许负数的属性:
public class Base
{
[NegativesAllowed]
public PositiveNumber Number { get; set; }
}
public class Derived : Base
{
public PositiveNumber Number { get; set; }
}
如果Base
允许所有数字,并且Derived
仅允许正数,那么它本身并不违反LSP。
然而,这似乎是一种非常强迫的情况。使用有限的类型,然后通过属性扩展,这不是你真实要遇到的。
对于您的情况,您根本不应该从另一个继承一个viewmodel。
需要不同属性的事实是您不应继承这些类的主要原因!他们应该彼此不同地工作,因此不应该假装一个是另一个的推导。
答案 4 :(得分:-3)
如果使用C#4.0,
如何编写'new'构造函数。
public new string PhoneNumber { get; set; }
我不确定它是否运作良好。