我有一个类,它是一个数据库中的实体,有一堆日期表示为字符串。例如,它可能是这样的:
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?
答案 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;
}