浏览代码

Added binding classes from Yoda project

Lukas Angerer 1 年之前
父节点
当前提交
9dde7b5f94
共有 4 个文件被更改,包括 114 次插入0 次删除
  1. 45 0
      Binding/ExpressionBuilder.cs
  2. 21 0
      Binding/IBinding.cs
  3. 8 0
      Binding/IMemberExpressionBinding.cs
  4. 40 0
      Binding/PropertyBinding.cs

+ 45 - 0
Binding/ExpressionBuilder.cs

@@ -0,0 +1,45 @@
+using System.Linq.Expressions;
+
+namespace BlazorEditForms.Binding;
+
+public static class ExpressionBuilder
+{
+    public static Expression<Func<TProperty>> CreateGetter<TProperty>(MemberExpression mex)
+    {
+        return Expression.Lambda<Func<TProperty>>(mex);
+    }
+
+    public static Expression<Action<TProperty>> CreateSetter<TProperty>(MemberExpression mex)
+    {
+        var valueParameter = Expression.Parameter(typeof(TProperty), "value");
+        var assign = Expression.Assign(mex, valueParameter);
+        return Expression.Lambda<Action<TProperty>>(assign, valueParameter);
+    }
+
+    public static Expression ReplaceParameter(Expression originalExpression, ParameterExpression parameter, Expression replacement)
+    {
+        return new ParameterReplacer(parameter, replacement).Visit(originalExpression);
+    }
+
+    /// <summary>
+    /// This visitor replaces a specific function parameter with an actual value given as another
+    /// expression.
+    /// </summary>
+    public class ParameterReplacer : ExpressionVisitor
+    {
+        private readonly ParameterExpression _parameter;
+        private readonly Expression _replacement;
+
+        public ParameterReplacer(ParameterExpression parameter, Expression replacement)
+        {
+            _parameter = parameter;
+            _replacement = replacement;
+        }
+
+        protected override Expression VisitParameter(ParameterExpression node)
+        {
+            // Replace the parameter with the provided expression
+            return node == _parameter ? _replacement : base.VisitParameter(node);
+        }
+    }
+}

+ 21 - 0
Binding/IBinding.cs

@@ -0,0 +1,21 @@
+namespace BlazorEditForms.Binding;
+
+public interface IBinding<T>
+{
+    T Get();
+    void Set(T value);
+}
+
+public interface IBindingMetadata
+{
+    string DisplayName { get; }
+}
+
+public interface IBindingValue<T> : IBinding<T>
+{
+    T Value
+    {
+        get => Get();
+        set => Set(value);
+    }
+}

+ 8 - 0
Binding/IMemberExpressionBinding.cs

@@ -0,0 +1,8 @@
+using System.Linq.Expressions;
+
+namespace BlazorEditForms.Binding;
+
+public interface IMemberExpressionBinding<T> : IBindingValue<T>, IBindingMetadata
+{
+    Expression<Func<T>> Expression { get; }
+}

+ 40 - 0
Binding/PropertyBinding.cs

@@ -0,0 +1,40 @@
+using System.ComponentModel;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace BlazorEditForms.Binding;
+
+public static class PropertyBinding
+{
+    public static PropertyBinding<TProperty> Create<TProperty>(Expression<Func<TProperty>> prop)
+    {
+        if (prop.Body is not MemberExpression memberExpression)
+        {
+            throw new Exception($"Expected expression Body to be a member expression, but got {prop.Body.GetType()}");
+        }
+        return new PropertyBinding<TProperty>(memberExpression);
+    }
+}
+
+public class PropertyBinding<TProperty> : IBinding<TProperty>, IBindingMetadata, IBindingValue<TProperty>, IMemberExpressionBinding<TProperty>
+{
+    private readonly Func<TProperty> _getter;
+    private readonly Action<TProperty> _setter;
+
+    public Expression<Func<TProperty>> Expression { get; }
+
+    public string DisplayName { get; }
+
+    public PropertyBinding(MemberExpression memberExpression)
+    {
+        Expression = ExpressionBuilder.CreateGetter<TProperty>(memberExpression);
+        _getter = Expression.Compile();
+        _setter = ExpressionBuilder.CreateSetter<TProperty>(memberExpression).Compile();
+
+        var displayAttr = memberExpression.Member.GetCustomAttributes<DisplayNameAttribute>().FirstOrDefault();
+        DisplayName = displayAttr?.DisplayName ?? "<Unknown>";
+    }
+
+    public TProperty Get() => _getter();
+    public void Set(TProperty value) => _setter(value);
+}