我有以下课程特许经营权:
public class Franchise
{
public string FolderName { get; set; }
public string InstallerExeName { get; set; }
}
我有一个方法可以检查db中所有特许经营权的uniqness的特定属性值。
public bool ValidateFolderName(string folderName)
{
var allFranchises = _franchiseService.GetAll();
var result = allFranchises.Any(f => f.FolderName == folderName);
return result;
}
问题是我必须检查另一个属性uniqness:
public bool ValidateInstallerExeName(string installerExeName)
{
var allFranchises = _franchiseService.GetAll();
var result = allFranchises.Any(f => f.InstallerExeName == installerExeName);
return result;
}
我希望通过制作通用方法来避免代码重复。类似的东西:
public bool ValidateProperty(string propertyName)
{
var allFranchises = _franchiseService.GetAll();
// Not sure how to write this line
var result = allFranchises.Any(f => f.[propertyName] == propertyName);
return result;
}
问题是我不知道如何重新编写这行代码,以便它可以获取属性名称并通过提供的参数检查其值:
var result = allFranchises.Any(f => f.[propertyName] == propertyName);
我知道我可以用反射来做这样的事情:
franchise.GetType().GetProperty(propertyName).GetValue(franchise, null);
但我不知道如何才能使其符合我的要求。任何有关工作示例的帮助将不胜感激。谢谢!
答案 0 :(得分:1)
public bool ValidateProperty<TType, TPropertyType>(Func<TType, TPropertyType> propertySelector, TPropertyType propertyValue)
{
return _franchiseService.GetAll().Any(f => propertySelector(f) == propertyValue);
}
您可以这样称呼它:
if( ValidateProperty(x => x.FirstName, "Joe") )
这不使用反射,你的属性名也有智能感知。
答案 1 :(得分:1)
以下是使用反射的完整工作示例:
class Program
{
private static List<Franchise> allFranchises;
static void Main(string[] args)
{
allFranchises = new List<Franchise>
{
new Franchise() { FolderName=@"c:\1", InstallerExeName="1.exe" },
new Franchise() { FolderName=@"c:\2", InstallerExeName="2.exe" },
new Franchise() { FolderName=@"c:\3", InstallerExeName="3.exe" },
new Franchise() { FolderName=@"c:\4", InstallerExeName="4.exe" },
new Franchise() { FolderName=@"c:\5", InstallerExeName="5.exe" },
};
Console.WriteLine(ValidateProperty("FolderName", @"c:\2", allFranchises));
Console.WriteLine(ValidateProperty("InstallerExeName", "5.exe", allFranchises));
Console.WriteLine(ValidateProperty("FolderName", @"c:\7", allFranchises));
Console.WriteLine(ValidateProperty("InstallerExeName", "12.exe", allFranchises));
}
public static bool ValidateProperty(string propertyName, object propertyValue, IEnumerable<Franchise> validateAgainst)
{
PropertyInfo propertyInfo = typeof(Franchise).GetProperty(propertyName);
return validateAgainst.Any(f => propertyInfo.GetValue(f, null) == propertyValue);
}
}
public class Franchise
{
public string FolderName { get; set; }
public string InstallerExeName { get; set; }
}
它会打印出来:
True
True
False
False
正如所料。
答案 2 :(得分:0)
您可以使用扩展方法:
public static bool ValidateProperty(
this IEnumerable<Franchise> franchises,
string property,
object value)
{
var prop = typeof(Franchise).GetProperty(property);
if (prop == null)
throw new ArgumentException("Property does not exist");
return franchises.Any(f =>
prop.GetValue(f) == value);
}
像这样使用:
var r = _franchiseService.GetAll().ValidateProperty("FolderName", "myfolder1");
答案 3 :(得分:0)
您可以使用System.Linq.Expressions
public class Franchise
{
public string FolderName { get; set; }
public string InstallerExeName { get; set; }
bool ValidateProperty(string propertyName) {
var allFranchises = new List<Franchise>();
var parameter = Expression.Parameter(typeof(Franchise));
var property = Expression.Property(parameter, propertyName);
var thisExpression = Expression.Constant(this, typeof(Franchise));
var value = Expression.Property(thisExpression, propertyName);
var notThis = Expression.ReferenceNotEqual(thisExpression, property);
var equal = Expression.Equal(value, property);
var lambda = Expression.Lambda<Func<Franchise, bool>>(Expression.And(notThis, equal));
// lamda is now the equivalent of:
// x => !object.ReferenceEquals(this, x) && object.Equals(x.Property, this.Property)
return allFranchises.Any(lambda.Compile());
}
}
如果allFranchises的类型为IQueryable,则使用allFranchises.Any(lambda)
如果您担心性能,也可以缓存表达式以供以后使用。 }