IndexerExpressionNode.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. namespace Avalonia.Data.Core
  7. {
  8. class IndexerExpressionNode : IndexerNodeBase
  9. {
  10. private readonly ParameterExpression _parameter;
  11. private readonly IndexExpression _expression;
  12. private readonly Delegate _setDelegate;
  13. private readonly Delegate _getDelegate;
  14. private readonly Delegate _firstArgumentDelegate;
  15. public IndexerExpressionNode(IndexExpression expression)
  16. {
  17. _parameter = Expression.Parameter(expression.Object.Type);
  18. _expression = expression.Update(_parameter, expression.Arguments);
  19. _getDelegate = Expression.Lambda(_expression, _parameter).Compile();
  20. var valueParameter = Expression.Parameter(expression.Type);
  21. _setDelegate = Expression.Lambda(Expression.Assign(_expression, valueParameter), _parameter, valueParameter).Compile();
  22. _firstArgumentDelegate = Expression.Lambda(_expression.Arguments[0], _parameter).Compile();
  23. }
  24. public override Type PropertyType => _expression.Type;
  25. public override string Description => _expression.ToString();
  26. protected override bool SetTargetValueCore(object value, BindingPriority priority)
  27. {
  28. try
  29. {
  30. _setDelegate.DynamicInvoke(Target.Target, value);
  31. return true;
  32. }
  33. catch (Exception)
  34. {
  35. return false;
  36. }
  37. }
  38. protected override object GetValue(object target)
  39. {
  40. try
  41. {
  42. return _getDelegate.DynamicInvoke(target);
  43. }
  44. catch (TargetInvocationException e) when (e.InnerException is ArgumentOutOfRangeException
  45. || e.InnerException is IndexOutOfRangeException
  46. || e.InnerException is KeyNotFoundException)
  47. {
  48. return AvaloniaProperty.UnsetValue;
  49. }
  50. }
  51. protected override bool ShouldUpdate(object sender, PropertyChangedEventArgs e)
  52. {
  53. return _expression.Indexer == null || _expression.Indexer.Name == e.PropertyName;
  54. }
  55. protected override int? TryGetFirstArgumentAsInt() => _firstArgumentDelegate.DynamicInvoke(Target.Target) as int?;
  56. }
  57. }