Skip to content

Instantly share code, notes, and snippets.

@glebov21
Last active January 11, 2017 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glebov21/12b89550f1d539845e4464187fce82f3 to your computer and use it in GitHub Desktop.
Save glebov21/12b89550f1d539845e4464187fce82f3 to your computer and use it in GitHub Desktop.
Property bindints without strings
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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment