4

我的班级MyClass<t>有以下方法

private static bool TypeHasProperty(string NameOfPropertyToMatch)
{
    var properties = typeof(t).GetProperties();
    var requiredProperty = properties.First(
            a => a.Name == NameOfPropertyToMatch);
    if (requiredProperty == null)
    {
        return false
    };

    return true;
}

这在静态方法的开头调用:

MyClass<t>.SendToJavaScript(t InstanceOfType, string NameOfPropertyWithinType).

在继续之前确保它InstanceOfType实际上具有该名称的属性,否则不会抛出异常,直到 waaaaaay 下线(此信息最终将被序列化并发送到 Javascript 应用程序,该应用程序需要知道要访问哪个属性为了完成它的工作)。

我想要一种好的、类型安全的方法来调用该方法,如果我决定稍后更改我的属性的名称,它不会导致验证失败。

例如,我不想这样称呼它:

MyClass<Person>.SendToJavaScript(MyPerson, "Name")

因为如果我决定在课堂上改变Name,我必须确保进来并改变那根魔法线。LastName,Person

我想要的是这样的:

MeClass<Person>.SendToJavaScript(
    MyPerson,
    TypeOf(Person).Properties.Name.ToString())

因此,如果我使用 Refactoring 更改NameLastName,IDE 将在那里扫描并更改我的调用。

有这样的东西存在吗?还是我在重构时只需要小心?(我爱我一些F2

4

2 回答 2

5

我们在代码中使用这样的东西:

private static bool TypeHasProperty<P>(Expression<Func<T, P>> accessor)
{
    var propertyName = ((MemberExpression)accessor.Body).Member.Name;
    var properties = typeof(T).GetProperties();
    return properties.Any(a => a.Name == propertyName);
}

用它:

class Foo
{
    public int Baz { get; set; }
}

MyClass<Foo>.TypeHasProperty(f => f.Baz);

编辑:将查询更改为使用Any(),因为它更好地表达了您实际想要做的事情(具有给定名称的属性是否存在?)

请注意,First()如果未找到匹配项,则会抛出。

于 2013-10-03T21:42:32.303 回答
4

尝试这个:

MeClass<Person>.SendToJavaScript(MyPerson, x => x.Name);

接着:

private static bool TypeHasProperty(Expression propertyExpression)
{
    var expression = GetMemberInfo(propertyExpression);
    string name = expression.Member.Name;

    return typeof(t).GetProperty(name) != null;
}

private static MemberExpression GetMemberInfo(Expression method)
{
    LambdaExpression lambda = method as LambdaExpression;
    if (lambda == null)
        throw new ArgumentNullException("method");

    MemberExpression memberExpr = null;

    if (lambda.Body.NodeType == ExpressionType.Convert)
    {
        memberExpr = 
            ((UnaryExpression)lambda.Body).Operand as MemberExpression;
    }
    else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
    {
        memberExpr = lambda.Body as MemberExpression;
    }

    if (memberExpr == null)
        throw new ArgumentException("method");

    return memberExpr;
}

从这里无耻地采取:从 lambda 表达式中检索属性名称

但这是一个稍微不同的问题,所以我发布了一个完整的答案。

我刚刚注意到,在我提供的第二个答案的链接中,这要简单得多。ChrisWue'a answer in this thread 涵盖了这一点。

于 2013-10-03T21:40:42.137 回答