在C#中验证属性

9

假设我有一个接口,并从它继承了一个类,

internal interface IPersonInfo
{
    String FirstName { get; set; }
    String LastName { get; set; }
}
internal interface IRecruitmentInfo
{
    DateTime RecruitmentDate { get; set; }
}

public abstract class Collaborator : IPersonInfo, IRecruitmentInfo
{
    public DateTime RecruitmentDate
    {
        get;
        set;
    }
    public String FirstName
    {
        get;
        set;
    }
    public String LastName
    {
        get;
        set;
    }
    public abstract Decimal Salary
    {
        get;
    }
}

那么我该如何在协作者类中验证字符串?能否在属性内部实现?
9个回答

10

可以,但不能使用自动属性。你需要手动实现带有备份字段的属性:

private string firstName;

public String FirstName
{
    get
    {
        return firstName;
    }
    set
    {
        // validate the input
        if (string.IsNullOrEmpty(value))
        {
            // throw exception, or do whatever
        }
        firstName = value;
    }
}

6

Something like this...

private string _firstName;
public string FirstName
{
    get
    {
        return _firstName;
    }
    set
    {
        if (value != "Bob")
          throw new ArgumentException("Only Bobs are allowed here!");
        _firstName = value;
    }
}

基本上,你使用的是语法糖版本的属性。在编译时,它们将创建一个私有成员变量,并将属性连接到使用该变量,就像我在这里手动做的那样。这样做的确切原因是,如果您想添加逻辑,您可以将其转换为手动方式,就像我在这里做的一样,而不会破坏接口实现。



3
如果您想变得更加复杂,还应该提到验证框架。它们可以使验证规则更易于管理,并将错误呈现给您的UI,同时将规则与您的模型绑定,因此您不必编写重复的样板验证代码。根据您的框架版本,一种选择是DataAnnotations

2
据我所知,如果使用自动属性语法,您将失去访问支持字段的能力。根据文档 (http://msdn.microsoft.com/en-us/library/bb384054.aspx) : 在 C# 3.0 及更高版本中,当属性访问器中不需要其他逻辑时,自动实现属性可以使属性声明更加简洁。它们还使客户端代码能够创建对象。当您像下面的示例一样声明一个属性时,编译器会创建一个私有的匿名后备字段,只能通过属性的 get 和 set 访问器进行访问。 自动实现属性上允许使用特性,但显然无法在后备字段上使用特性,因为这些字段不能从源代码中访问。如果必须在属性的后备字段上使用属性,则只需创建一个普通属性即可。
因此,您唯一的解决方案是创建普通属性。

0

可以的。你可以为属性创建一个私有后备字段,像这样:

private String _firstName;

public String FirstName
{
     get
     {
          return _firstName;
     }
     set
     {
          //Check value for correctness here:
          _firstName = value;
     }
}

0
private DateTime recruitmentDate;    
public DateTime RecruitmentDate
{
    get { return recruitmentDate; }
    set
    {
        validate(value);
        recruitmentDate = value;
    }
}

0
如果你的意思是在C#属性的get/set期间执行自定义逻辑,那么答案是肯定的。
你正在使用所谓的自动属性,其中后备存储和逻辑已为您默认设置。
你只需要像这样提供它:
private int backingStoreVariable;
public property MyProperty
{
    get
    {
        return this.backingStoreVariable;
    }
    set
    {
        this.backingStoreVariable=value;
    }
}

现在您可以在get和set块中运行自定义验证代码。

0

或者,您可以不使用值类型来定义字段。例如,您可以创建一个名为“FirstName”的类,并使用以下实现:

public class FirstName
{
    private string _Value;
    public string Value
    {
        get
        {
            return _Value;
        }
        set
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentNullException("Value cannot be null");
            if (value.Length > 128)
                throw new ArgumentOutOfRangeException("Value cannot be longer than 128 characters");
            _Value  = value;
        }
    }

    public FirstName(string initialValue)
    {
        Value   = initialValue; //does validation check even in constructor
    }
}

最后,在上面的代码示例中,你只需简单地有:
public interface IPersonInfo
{
    FirstName FirstName { get; set; }
    String LastName { get; set; }
}

接下来用你的其他属性同样的方法操作。 然后在你的代码中使用该属性,你可以这样写:

public FirstName MyFirstName;
var x = MyFirstName.Value;

如果您有很多要验证的字段,这可能会变得繁琐。但是,您可以将其概括为处理某些类型的数字-例如正数(ints > 0)或计数(int >= 0),度量等。

字符串更难处理,因为它们通常除了值类型(如无特殊字符、无数字等)外还有长度限制。通过在继承类的构造函数中设置只读长度属性,可能可以解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接