8

我有一个电话号码通知模型(用户通过与他们的帐户相关联的电话号码收到紧急情况通知,他们可以设置这些电话号码的顺序)。大多数时候,模型的电话号码部分是必需的,但在创建新用户期间有一个特殊情况,我们不想强制它。

我制作了一个非常简单的子对象 UserCreationPhoneNotificationModel,它继承自上述 UserPhoneNotificationModel。还有一些其他小的更改,但这里的相关更改是覆盖 PhoneNumber 字段,因此不再需要它。

在父模型中

[Required]
public virtual string PhoneNumber { get; set; }

在子模型中,它只是

public override string PhoneNumber { get; set; }

我认为这可以解决问题,但显然不是。我认为问题在于RequiredAttribute 会有 Inherited = true ,但事实并非如此,所以我不完全确定为什么它会被继承到子类中。

我做了仔细检查以确保,从父类的字段中删除Required也使得子类中的字段不是必需的,所以它绝对是某种继承的东西。

4

5 回答 5

5

可以通过用同名的新属性隐藏现有属性来完成。所以,如果父类中的属性是这样的:

[Required]
public virtual string PhoneNumber { get; set; }

您可以像这样在子类中定义新属性:

public new string PhoneNumber { get; set; }

这将在子类中隐藏 PhoneNumber 属性及其属性。现在您可以使用它的任何其他属性。例如,您可以将[PhoneNumber]属性添加到子类中的属性。

于 2019-07-29T14:57:54.977 回答
4

当您正在建模的关系不适合时,使用继承来共享行为可能会出现问题。您通常不会从使用继承在 ViewModel 之间共享行为中获得任何好处,而您可能(并且,在您的情况下,确实)遇到问题。

您最好的选择是为每个用例使用不同的模型类。如果您真的需要在 ViewModel 之间共享行为,您可以通过组合来实现。

于 2013-06-25T07:44:37.723 回答
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; }
}

这是登录模型,我已经继承到另一个模型,但不需要电子邮件,它的代码如下:

public class ExternalLoginModel : SigninModel
{
    public override string email { get; set; }
    public string LoginProvider { get; set; }
    public string ProviderKey { get; set; }
}

我已经覆盖了另一个模型中的电子邮件属性

于 2018-03-27T07:53:00.723 回答
-2

如果使用 C# 4.0,

如何编写“新”构造函数。

public new string PhoneNumber { get; set; }

我不确定它是否有效。

于 2013-06-25T07:03:08.587 回答
-2

不继承属性是没有意义的

重写时删除[Required]属性本质上违反了LSP

如果NotRequiredDerived是 的子类型RequiredBase,则类型对象RequiredBase可以替换为类型对象NotRequiredDerived(即类型对象RequiredBase可以替换为子类型的任何对象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。

然而,这似乎是一个非常强迫的情况。使用一个有限的类型,然后通过一个属性来扩展,这不是你实际会遇到的事情。


对于您的情况,您根本不应该从另一个视图模型继承一个视图模型。

需要不同属性的事实是您不应该继承这些类的主要原因!他们应该以不同的方式工作,因此不应该假装一个是另一个的派生。

于 2018-03-27T09:00:53.833 回答