我有以下情况
我有一堆简单的类,例如这个
public class Student
{
public int Id { get; set; }
public int Age { get; set; }
public decimal AverageMark { get; set; }
public string Name { get; set; }
public string University { get; set; }
}
每个用户都可以创建,编辑和删除的网页。当我们创建更新学生时,我们需要对其进行验证。
问题是我们在编译期间不知道验证规则!!!
我们为管理员设置了单独的网页,他设置了验证标准,
例如,学生年龄不能低于15或大学必须等于“SomeUniversity”。
结果我有一些存储在我的数据库中的标准列表
public class Criteria
{
public string PropertyName { get; set; }
public string OperationName { get; set; }
public string OperationValue { get; set; }
}
我为调查目的创建了简单的控制台应用程序。这是代码
namespace DynamicValidation
{
class Program
{
static void Main(string[] args)
{
//set up students
var student1 = new Student() { Age = 20, AverageMark = 4, Name = "Ihor", University = "Lviv National University" };
var student2 = new Student() { Age = 20, AverageMark = 4, Name = "Taras", University = "Lviv National University" };
var student3 = new Student() { Age = 20, AverageMark = 5, Name = "Marko", University = "" };
var student4 = new Student() { Age = 20, AverageMark = 3, Name = "Tanya", University = "" };
var student5 = new Student() { Age = 22, AverageMark = 4, Name = "Ira", University = "" };
var students = new List<Student>() { student1, student2, student3, student4, student5 };
//set up validation rules
var criteria1 = new Criteria("Age", "Equal", "20");
var criteria2 = new Criteria("AverageMark", "NotLessThan", "4");
var criteria3 = new Criteria("University", "Contains", "Lviv");
var criterias = new List<Criteria>() { criteria1, criteria2, criteria3 };
var result = new List<Student>();
foreach (var currentStudent in students)
{
foreach (var currentCriteria in criterias)
{
object currentPropertyValue = typeof(Student).GetProperty(currentCriteria.PropertyName).GetValue(currentStudent);
//what is next ???!!!
}
}
}
}
public class Student
{
public int Id { get; set; }
public int Age { get; set; }
public decimal AverageMark { get; set; }
public string Name { get; set; }
public string University { get; set; }
}
public class Criteria
{
public string PropertyName { get; set; }
public string OperationName { get; set; }
public string OperationValue { get; set; }
}
}
我如何实现这段代码? (表达树,动态吗?)
我不希望你为我工作但也许有一些关于这个的文章? (我试图找到但没有成功)
也许有一些关于方法的建议?
也许有一些类似的开放代码?
或者它可能已经在一些图书馆中实施了?
将感谢任何帮助:)
答案 0 :(得分:2)
您可以编写学生验证函数,请参阅IsValidStudent(Criteria criteria)
:
public class Student
{
public int Id { get; set; }
public int Age { get; set; }
public decimal AverageMark { get; set; }
public string Name { get; set; }
public string University { get; set; }
public bool IsValidStudent(Criteria criteria)
{
return IsValidByAge(criteria)
&& IsValidByMarks(criteria)
&& IsValidByUniversity(criteria);
}
private bool IsValidByAge(Criteria criteria)
{
switch (criteria.OperationType)
{
case Criteria.Operation.GreaterThan:
return Convert.ToInt32(criteria.OperationValue) > this.Age;
case Criteria.Operation.LessThan:
return Convert.ToInt32(criteria.OperationValue) < this.Age;
case Criteria.Operation.EqualTo:
return Convert.ToInt32(criteria.OperationValue) == this.Age;
default:
return false;
}
}
private bool IsValidByMarks(Criteria criteria)
{
// etc...
}
private bool IsValidByUniversity(Criteria criteria)
{
// etc...
}
}
用法:
var result = new List<Student>();
foreach (var currentStudent in students)
{
foreach (var currentCriteria in criterias)
{
if (currentStudent.IsValidStudent(currentCriteria))
{
result.Add(currentStudent);
}
}
}
我还扩展了你的Criteria
课程:
public class Criteria
{
public string PropertyName { get; set; }
public Operation OperationType { get; set; }
public string OperationValue { get; set; }
public enum Operation
{
EqualTo,
GreaterThan,
LessThan,
Contains
}
public Criteria(string propertyName, Operation operationType, string operationValue)
{
this.PropertyName = propertyName;
this.OperationType = operationType;
this.OperationValue = operationValue;
}
}
答案 1 :(得分:0)
public interface IValidator
{
bool Validate(object value, object validateWith);
}
一组实施
public class ContainsValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
string valueString = Convert.ToString(value);
string validateWithString = Convert.ToString(validateWith);
return valueString.Contains(validateWithString);
}
}
public class StartWithValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
string valueString = Convert.ToString(value);
string validateWithString = Convert.ToString(validateWith);
return valueString.StartsWith(validateWithString);
}
}
public class LengthValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
string valueString = Convert.ToString(value);
int valueLength = Convert.ToInt32(validateWith);
return (valueString.Length == valueLength);
}
}
public class LessThanValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
decimal valueDecimal = Convert.ToDecimal(value);
decimal validateWithDecimal = Convert.ToDecimal(validateWith);
return (valueDecimal < validateWithDecimal);
}
}
public class MoreThanValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
decimal valueDecimal = Convert.ToDecimal(value);
decimal validateWithDecimal = Convert.ToDecimal(validateWith);
return (valueDecimal > validateWithDecimal);
}
}
public class EqualValidator : IValidator
{
public bool Validate(object value, object validateWith)
{
string valueString = Convert.ToString(value);
string validateWithString = Convert.ToString(validateWith);
return (valueString == validateWithString);
}
}
和用法
class Program
{
static void Main(string[] args)
{
//set up students
var student1 = new Student() { Age = 20, AverageMark = 5, Name = "Ihor", University = "Lviv National University" };
var student2 = new Student() { Age = 20, AverageMark = 5, Name = "SomeLongName", University = "Lviv National University" };
var student3 = new Student() { Age = 20, AverageMark = 5, Name = "Taras", University = "Kyiv National University" };
var student4 = new Student() { Age = 20, AverageMark = 5, Name = "Marko", University = "Some University" };
var student5 = new Student() { Age = 20, AverageMark = 4, Name = "Tanya", University = "Lviv National University" };
var student6 = new Student() { Age = 22, AverageMark = 4, Name = "Ira", University = "" };
var students = new List<Student>() { student1, student2, student3, student4, student5, student6 };
//set up validation rules
var criteria1 = new Criteria("Age", "Equal", "20");
var criteria2 = new Criteria("AverageMark", "MoreThen", "4");
var criteria3 = new Criteria("University", "Contains", "National");
var criteria4 = new Criteria("University", "StartWith", "Lviv");
var criteria5 = new Criteria("Name", "Length", "4");
var criterias = new List<Criteria>() { criteria1, criteria2, criteria3, criteria4, criteria5 };
var result = new List<Student>();
foreach (var currentStudent in students)
{
var isValid = true;
foreach (var currentCriteria in criterias)
{
object currentPropertyValue = typeof(Student).GetProperty(currentCriteria.PropertyName).GetValue(currentStudent);
IValidator currentValidator = ValidatorFactory.GetValidator(currentCriteria.OperationName);
bool validationResult = currentValidator.Validate(currentPropertyValue, currentCriteria.OperationValue);
if (!validationResult)
{
isValid = false;
break;
}
}
if (isValid)
result.Add(currentStudent);
}
}
}
最后是ValidatorFactory的代码
public class ValidatorFactory
{
public static IValidator GetValidator(string validatorName)
{
validatorName = validatorName.ToUpper();
switch (validatorName)
{
case "CONTAINS": return new ContainsValidator();
case "STARTWITH": return new StartWithValidator();
case "EQUAL": return new EqualValidator();
case "MORETHEN": return new MoreThanValidator();
case "LENGTH": return new LengthValidator();
default: throw new Exception("There are not appropriate validator.");
}
}
}
也许这将有助于未来的人:)