C#:获取属性的名称并检查其值

时间:2014-01-06 11:48:34

标签: c# reflection

我有以下课程特许经营权:

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

但我不知道如何才能使其符合我的要求。任何有关工作示例的帮助将不胜感激。谢谢!

4 个答案:

答案 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)

如果您担心性能,也可以缓存表达式以供以后使用。     }