在Xamarin PCL中按名称验证是否存在非公共财产

时间:2017-01-18 12:04:48

标签: c# xamarin system.reflection

问题:

在Xamarin PCL项目中,对于公开的属性,有没有办法验证具有给定名称的属性是否存在?

上下文:

在我的ViewModelBase类中,OnPropertyChanged调用仅调试方法。它帮助我找到OnPropertyChanged的错误参数,以防我无法使用CallerMemberName逻辑并且必须传递propertyName的显式值:

public abstract class ViewModelBase : INotifyPropertyChanged
{

  // ...

  protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    VerifyPropertyName(propertyName);
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    // More code that is the reason why calling OnPropertyChanged can
    // make sense even for private or protected properties in my code.
  }

  [Conditional("DEBUG"), DebuggerStepThrough]
  private void VerifyPropertyName(string propertyName)
  {
    // This only finds public properties
    if (GetType().GetRuntimeProperty(propertyName) == null) {
      // TODO
      // Check if there is a non-public property
      // If there is, only print a hint
      throw new ArgumentException("Invalid property name: " + propertyName);
    }
  }

  // ...

}

问题是GetRuntimeProperty只找到公共属性,即。即为私有属性调用OnPropertyChanged会触发该异常。

我想削弱条件,以便为非公共属性调用OnPropertyChanged只触发Debug.Print,因为我的ViewModelBase.OnPropertyChanged包含更多代码,因此调用OnPropertyChanged 可以对私人或受保护的财产有益。

System.Type获得的GetType()对象和System.Reflection.TypeInfo获得的GetType().GetTypeInfo()对象in this SO answer似乎都没有找到除公共属性。

2 个答案:

答案 0 :(得分:1)

实际答案,按照Furkan Fidan's comment

GetRuntimeProperty仅查找公共属性,因此如果给定属性不公开,则返回null

但是,您可以通过调用GetRuntimeProperties方法检索所有属性的列表(包括非公开属性)。然后,您可以使用LINQ过滤结果。

private void VerifyPropertyName(string propertyName)
{
  if (GetType().GetRuntimeProperty(propertyName) != null) {
    // The property is public
  } else if (GetType().GetRuntimeProperties().Any(p => p.Name == propertyName)) {
    // The property is not public, but it exists
  } else {
    // The property does not exist
  }
}

另见GetRuntimeProperties的评论:

  

此方法返回在指定类型上定义的所有属性,包括继承,非公共,实例和静态属性。

答案 1 :(得分:0)

您可以通过将非公开binding flag传递给GetFields方法来获取某种类型的私有字段。请参阅下面的快速而肮脏的示例。

using System;
using System.Reflection;

class MyClass
{
    private int privField;

    public MyClass(int val)
    {
        this.privField = val;
    }

    public void printValueOfPrivate()
    {
        var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
        Console.WriteLine("Name: " + fields[0].Name + " Value: " + fields[0].GetValue(this));
    }
}

public class HelloWorld
{
    static public void Main()
    {
        var mc = new MyClass(7);
        mc.printValueOfPrivate();
    }
}

输出:

Name: privField Value: 7

修改

请参阅注释以获取详细信息,但基本上要实现@LWChris希望您在GetType()上调用GetRuntimeProperties(),因为GetRuntimeProperty()不返回私有属性。