有没有办法使这个验证通用?

时间:2013-06-20 04:03:01

标签: c# .net-3.5

我有一个类,它是一个数据库中的实体,有一堆日期表示为字符串。例如,它可能是这样的:

public class Stuff
{
    public string Date1 {get;set;}
    public string Date2 {get;set;}
    public string Date3 {get;set;}
    public string Date4 {get;set;}
}

然后我有一个Validation方法验证其他属性并验证日期属性。目前,我正在为每个对象单独验证每个日期。这是有效的,但我想知道是否有一种方法可以使它通用,所以我不必跨类和类本身复制代码。我目前正在做类似的事情:

public bool ValidateDate(string date)
{
    string[] overrides = {"","__/__/____"};

    bool success = true;
    DateTime dateTime;

    if(!overrides.Contains(date) && !DateTime.TryParse(date,out dateTime))
    {
        success = false;
    }


    return success;
}

//Notice in this method I am repeating the if statements.
public bool Validate(Stuff stuff, out string message)
{
    message = string.Empty;
    bool success = true;

    if(!ValidateDate(stuff.Date1))
    {
        success = false;
        message = "Date 1 is invalid";
    }

    if(!ValidateDate(stuff.Date2))
    {
        success = false;
        message = "Date 2 is invalid";
    }

    if(!ValidateDate(stuff.Date3))
    {
        success = false;
        message = "Date 3 is invalid";
    }

    if(!ValidateDate(stuff.Date4))
    {
        success = false;
        message = "Date 4 is invalid";
    }

    return success;
}

void Main()
{
    string message;

    Stuff stuff = new Stuff();
    stuff.Date1 = "01/01/2020";
    stuff.Date2 = "__/__/____";
    stuff.Date3 = "";
    stuff.Date4 = "44/__/____";


    bool valid = Validate(stuff, out message);

}

我想做类似的事情:

public bool Validate<T>(T value, out string message)
{
    //Validation here
}

但是,如果我错了,请纠正我,但这需要我获取属性并使用反射来检查日期的值,而我的另一个问题是属性是字符串,所以没有办法我来检查它是否是DateTime?

3 个答案:

答案 0 :(得分:1)

我觉得我错过了一些信息 - 现在我看到的重复是你多次调用ValidateDate。我认为没有办法解决这个问题 - 您必须在每个Date属性上调用Validate,除非(如您所述)您想要进入反射路径。

通过反射,您只需遍历所有属性并查找名称与模式Date[number]匹配的任何属性,然后您将验证它确实是DateTime(与您一样Parse已经做了)然后继续前进。

如果字段数已知并且不是太多,我会坚持使用ValidateMethod,但请注意message目前只会向您显示上一个错误(每次都会被覆盖)。

你可以变得可爱并且写一个像这样的方法:

public bool Validate(Stuff stuff, out string message)
{
    message = "Invalid Date(s): ";

    return ValidateDates(ref message, stuff.Date1, stuff.Date2, stuff.Date3, stuff.Date4);
}

public bool ValidateDate(ref string message, params string[] dates)
{
    bool rv = true;

    for (int i = 0; i < dates.Length; i++)
    {
        if (![validate DateTime as above])
        {
            message += i + " "; // add the failed index to the message
            rv = false;
        }
    }
    return rv;
}

答案 1 :(得分:0)

你可以做的最好的事情可能就是这样,虽然我不主张使用字符串来表示日期。

public bool ValidateDates(params string[] dates)
{
    return dates.All( d => ValidateDate(d));
}

public bool Validate(Stuff stuff, out string message)
{

    ValidateDates(stuff.Date1,stuff.Date2,stuff.Date3);
}

显然,您可以通过此方式来了解哪个日期失败,例如您可以执行类似

的操作
var item = dates.Select( d, i => new 
{
   Valid = ValidateDate(d),
   Message = String.Format("Date {0} failed", i)
}).FirstOrDefault( x => !x.Valid);

if(item == null) //everything is valid
  return true;
else 
   //set the out param
   outMessageStr = item.Message;

return false;

答案 2 :(得分:0)

可以通过使用你想要获取日期的对象的接口来使一切变得通用。

例如:

//Defines an interface that provides a function to get multiple dates from an object.
public interface IGetDates
{
     //You could use a Read-Only property too
     string[] GetDates();
}

public class Stuff : IGetDate
{
     //other stuff...

     public string[] GetDates()
     {
          return new[]{ Date1, Date2, Date2, ect...};
     }
}

然后您的通用方法如下所示:

//Uses generic constraints so only objects that use the 
//IGetDates interface can call this method.
public bool Validate<T>(T stuff, out string message) where T : IGetDates
{
     message = string.Empty;
     bool success = true;
     string[] dates = stuff.GetDates();
     for(int i = 0; i < dates.Length; i++)
     {
          if(!Validate(dates[i]))
          {
              success = false;
              message = string.Format("Date {0} is invalid.", i);
          }
     }
     return success;
}