简体   繁体   English

验证c#中的属性

[英]Validating properties in c#

let's suggest I got an interface and inherit class from it, 我建议我有一个接口并从中继承类,

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;
    }
}

then how do I validate strings in collaborator class? 那么如何验证协作者类中的字符串? Is it possible to implement inside properties? 是否可以实现内部属性?

Yes, but not using auto-properties. 是的,但不使用自动属性。 You will need to manually implement the properties with a backing field: 您需要使用支持字段手动实现属性:

private string firstName;

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

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;
    }
}

Basically, what you're using for properties are the syntactic sugar version. 基本上,你用于属性的是语法糖版本。 At compile time they create a private member variable and wire up the property to use that variable, as I'm doing manually here. 在编译时,他们创建一个私有成员变量并连接属性以使用该变量,因为我在这里手动完成。 The exact reason for this is so that if you want to add logic you can convert it into a manual one like I have here without breaking the implementation of the interface. 这样做的确切原因是,如果你想添加逻辑,你可以将它转换成手动的,就像我在这里一样,而不会破坏界面的实现。

Should also mention validation frameworks if you're getting a bit more sophisticated. 如果你有点复杂,还应该提一下验证框架。 They can make validation rules much easier to manage, and will also surface errors to your UI, whilst keeping the rules tied to your models so you don't have to have any repetitive boilerplate validation code. 它们可以使验证规则更易于管理,并且还会向UI显示错误,同时保持规则与模型相关联,因此您不必具有任何重复的样板验证代码。 Depending on your framework version, one option is DataAnnotations . 根据您的框架版本,一个选项是DataAnnotations

As far as I know, if you use the automatic properties syntax, you lose the ability to access the backing fields. 据我所知,如果使用自动属性语法,则无法访问支持字段。 According to the documentation (http://msdn.microsoft.com/en-us/library/bb384054.aspx): 根据文档(http://msdn.microsoft.com/en-us/library/bb384054.aspx):

In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors. 在C#3.0及更高版本中,当属性访问器中不需要其他逻辑时,自动实现的属性使属性声明更简洁。 They also enable client code to create objects. 它们还使客户端代码能够创建对象。 When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors. 当您声明属性时,如以下示例所示,编译器将创建一个私有的匿名支持字段,该字段只能通过属性的get和set访问器进行访问。

Attributes are permitted on auto-implemented properties but obviously not on the backing fields since those are not accessible from your source code. 允许在自动实现的属性上使用属性,但显然不在支持字段上,因为无法从源代码访问这些属性。 If you must use an attribute on the backing field of a property, just create a regular property. 如果必须在属性的支持字段上使用属性,只需创建常规属性。

So your only solution is to create regular properties. 因此,您唯一的解决方案是创建常规属性。

Alternatively, you could not use value types for your fields. 或者,您不能为字段使用值类型。 For instance, you could create a "FirstName" class with the following implementation: 例如,您可以使用以下实现创建“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
    }
}

Finally, in your code sample above you would simply have: 最后,在上面的代码示例中,您只需:

public interface IPersonInfo
{
    FirstName FirstName { get; set; }
    String LastName { get; set; }
}

and so on with your other properties. 等等你的其他财产。 Then to use the property in your codel, you would have: 然后要在您的codel中使用该属性,您将拥有:

public FirstName MyFirstName;
var x = MyFirstName.Value;

If you have a lot of fields that you want to validate, this might end up being a cumbersome approach. 如果您有许多要验证的字段,这可能最终会成为一种繁琐的方法。 However, you could generalize it to handle certain types of numbers - like positive numbers ( ints > 0 ), or counts ( int >= 0 ), measures, etc. 但是,您可以将其概括为处理某些类型的数字 - 例如正数( ints > 0 )或count( int >= 0 ),度量等。

Strings are harder because they often have length restrictions in addition to value types (such as no special characters, no digits, etc. This might be possible to accomodate by having a read-only length property that is set in the constructor of the inheriting class. 字符串更难,因为它们除了值类型之外通常还有长度限制(例如没有特殊字符,没有数字等。这可能通过在继承类的构造函数中设置的只读长度属性来适应。

Yes. 是。 You can create a private backing field for the property, like this: 您可以为属性创建私有支持字段,如下所示:

private String _firstName;

public String FirstName
{
     get
     {
          return _firstName;
     }
     set
     {
          //Check value for correctness here:
          _firstName = value;
     }
}
private DateTime recruitmentDate;    
public DateTime RecruitmentDate
{
    get { return recruitmentDate; }
    set
    {
        validate(value);
        recruitmentDate = value;
    }
}

If you mean can you perform custom logic during the get/set of a property in C#, the answer is yes. 如果你的意思是你可以在C#中获取/设置属性期间执行自定义逻辑,答案是肯定的。

Your using what are called Automatic Properties where the backing store and logic is defaulted for you. 您使用所谓的自动属性,其中后备存储和逻辑默认为您。

You just need to provide it yourself like 你只需要自己提供就好

private int backingStoreVariable;
public property MyProperty
{
    get
    {
        return this.backingStoreVariable;
    }
    set
    {
        this.backingStoreVariable=value;
    }
}

Now you can run custom validation code in your get and set blocks. 现在,您可以在get和set块中运行自定义验证代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM