csharp 没有字符串的属性绑定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 没有字符串的属性绑定相关的知识,希望对你有一定的参考价值。

public struct Binding
    {
        //WeakReference for garbige collection

        public System.Reflection.PropertyInfo To;
        public System.Reflection.PropertyInfo From; //memberinfo, methodinfo
        public WeakReference ToSource;
        public WeakReference FromSource;
        public Delegate Convertation;
    }

    public static class Bindings
    {
        private static object BindingLock = new object();
        private static Dictionary<object, List<Binding>> allBindings = new Dictionary<object, List<Binding>>();

        private static void UpdateBindings<TSource, TProperty>(object view, TSource concreteSource = default(TSource), Expression<Func<TSource, TProperty>> concreteProperty = null)
        {
            lock (BindingLock)
            {
                System.Reflection.PropertyInfo propInfo = null;
                if (concreteProperty != null)
                    propInfo = GetPropertyInfo(concreteSource, concreteProperty);
                var viewBind = allBindings[view];
                Binding binding;
                List<Binding> bindingsToRemove = new List<Binding>();
                for (int i = 0; i < viewBind.Count; i++)
                {
                    binding = viewBind[i];
                    if (concreteProperty != null)
                    {
                        if (binding.From != propInfo)
                            continue;
                    }

                    if (!binding.FromSource.IsAlive || !binding.ToSource.IsAlive)
                    {
                        //if (binding.ToSource.IsAlive)
                        //    binding.To.SetValue(binding.ToSource.Target, null, null); //set default value
                        bindingsToRemove.Add(binding);
                    }
                    else
                    {
                        if (binding.Convertation != null)
                            binding.To.SetValue(binding.ToSource.Target, binding.Convertation.DynamicInvoke(binding.From.GetValue(binding.FromSource.Target)));
                        else
                            binding.To.SetValue(binding.ToSource.Target, binding.From.GetValue(binding.FromSource.Target));
                    }
                }

                foreach (var bindingToRemove in bindingsToRemove)
                    viewBind.Remove(bindingToRemove);
            }
        }

        /// <summary>
        /// Update all bindings in view
        /// </summary>
        public static void UpdateBindings<TSource>(TSource view)
        {
            UpdateBindings<TSource, int>(view);
        }

        /// <summary>
        /// Change property and update bindings from this property
        /// </summary>
        public static void SetPropAndUpdateBindings<TSource, TProperty>(object view, TSource source, Expression<Func<TSource, TProperty>> property, TProperty value)
        {
            GetPropertyInfo(source, property).SetValue(source, value);
            UpdateBindings(view, source, property);
        }

        /// <summary>
        /// Bind objects in this view
        /// </summary>
        public static void Bind<TToSource, TToProperty, TFromSource, TFromProperty>(object view, TToSource toSource, Expression<Func<TToSource, TToProperty>> toProperty, TFromSource fromSource, Expression<Func<TFromSource, TFromProperty>> fromProperty, Func<TFromProperty, TToProperty> convertation = null)
        {
            lock (BindingLock)
            {
                if (!allBindings.ContainsKey(view))
                    allBindings[view] = new List<Binding>();

                allBindings[view].Add(new Binding()
                {
                    To = GetPropertyInfo<TToSource, TToProperty>(toSource, toProperty),
                    From = GetPropertyInfo<TFromSource, TFromProperty>(fromSource, fromProperty),
                    Convertation = convertation,
                    ToSource = new WeakReference(toSource),
                    FromSource = new WeakReference(fromSource)
                });
            }
        }

        private static System.Reflection.PropertyInfo GetPropertyInfo<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> propertyLambda)
        {
            Type type = typeof(TSource);

            MemberExpression member = propertyLambda.Body as MemberExpression;
            if (member == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a method, not a property.",
                    propertyLambda.ToString()));

            System.Reflection.PropertyInfo propInfo = member.Member as System.Reflection.PropertyInfo;
            if (propInfo == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a field, not a property.",
                    propertyLambda.ToString()));

            if (type != propInfo.ReflectedType &&
                !type.IsSubclassOf(propInfo.ReflectedType))
                throw new ArgumentException(string.Format(
                    "Expresion '{0}' refers to a property that is not from type {1}.",
                    propertyLambda.ToString(),
                    type));

            return propInfo;
        }
    }
    
    public class TestClass
    {
        public int TestProp { get; set; }
    }
    
    public class View
    {
        TestClass tFrom = new TestClass();
        TestClass tTo = new TestClass();
        
        public View()
        {
            Bindings.Bind(this, tTo, x => x.TestProp, tFrom, x => x.TestProp, (from) => { return from; });
        }

        public void Test()
        {
            tFrom.TestProp = 10;
            Bindings.UpdateBindings(this);

            //OR
            Bindings.SetPropAndUpdateBindings(this, tFrom, x => x.TestProp, 15);
        }
    }

以上是关于csharp 没有字符串的属性绑定的主要内容,如果未能解决你的问题,请参考以下文章

csharp 获取属性名称为字符串

csharp 数据注释属性,用于验证字符串是否为有效的XML

csharp 字符串属性允许使用下拉框和MVC模型验证

csharp 用于构建HTTP查询字符串的类(要分配给UriBuilder.Query属性)。

csharp 验证至少有一个给定属性具有值(如果字符串也检查空字符串)

如果值被模型绑定器绑定,则应用所需属性