using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Concurrent;
using System.Linq;
using System.ComponentModel;
using System.Reflection;
using CPF.Reflection;
using System.Timers;
using CPF.Controls;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Linq.Expressions;
using System.Threading;
using System.Diagnostics;
namespace CPF
{
///
/// 绑定
///
public class Binding : IDisposable
{
static ConcurrentDictionary> notifys = new ConcurrentDictionary>();
static Thread GCTimer;
//internal static bool runGC = true;
///
/// 事件弱绑定
///
///
/// 不能是静态方法
public static void RegisterPropertyChanged(INotifyPropertyChanged notify, PropertyChangedEventHandler propertyChanged)
{
if (propertyChanged.Method.IsStatic)
{
throw new Exception("不能是静态方法,必须关联对象");
}
if (GCTimer == null)
{
GCTimer = new Thread(GCTimer_Elapsed);
GCTimer.IsBackground = true;
GCTimer.Name = "清理无效绑定";
GCTimer.Start();
}
if (!notifys.TryGetValue(new WeakNode(notify), out HashSet list))
{
notify.PropertyChanged += Notify_PropertyChanged;
list = new HashSet();
notifys.TryAdd(new WeakNode(notify), list);
}
list.Add(new WeakDelegate(propertyChanged.Target, propertyChanged.Method));
}
private static void GCTimer_Elapsed()
{
while (true)
{
Thread.Sleep(5000);
List remove = new List();
foreach (var item in notifys)
{
//if(!item.Key.reference.IsAlive)
if (!item.Key.reference.TryGetTarget(out INotifyPropertyChanged notifyProperty) || (notifyProperty is IDisposed cpf && cpf.IsDisposed))
{
remove.Add(item.Key);
}
}
if (remove.Count > 0)
{
foreach (var item in remove)
{
notifys.TryRemove(item, out _);
}
GC.Collect();
}
}
}
private static void Notify_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (notifys.TryGetValue(new WeakNode((INotifyPropertyChanged)sender), out HashSet list))
{
List ids = new List();
List invokes = new List();
foreach (var item in list)
{
item.reference.TryGetTarget(out var t);
if (t == null || (t is IDisposed cpf && cpf.IsDisposed))
{
ids.Add(item);
}
else
{
//item.method.FastInvoke(t, sender, e);
invokes.Add(item);
}
}
foreach (var item in invokes)
{
item.reference.TryGetTarget(out var t);
if (t == null)
{
ids.Add(item);
}
else
{
item.method.FastInvoke(t, sender, e);
}
}
for (int i = 0; i < ids.Count; i++)
{
list.Remove(ids[i]);
}
}
}
///
/// 移除弱事件绑定
///
///
///
public static void CancellationPropertyChanged(INotifyPropertyChanged notify, PropertyChangedEventHandler propertyChanged)
{
var node = new WeakNode(notify);
if (notifys.TryGetValue(node, out HashSet list))
{
List ids = new List();
var wd = new WeakDelegate(propertyChanged.Target, propertyChanged.Method);
if (list.Contains(wd))
{
ids.Add(wd);
}
//foreach (var item in list)
//{
// //var t = item.reference.Target;
// //if (t == null || (propertyChanged.Target == t && propertyChanged.Method == item.method))
// if (!item.reference.IsAlive)
// {
// ids.Add(item);
// }
//}
if (ids.Count == list.Count)
{
list.Clear();
}
else
{
for (int i = 0; i < ids.Count; i++)
{
list.Remove(ids[i]);
}
}
if (list.Count == 0)
{
notifys.TryRemove(node, out _);
notify.PropertyChanged -= Notify_PropertyChanged;
}
}
}
struct WeakNode
{
public WeakNode(INotifyPropertyChanged reference)
{
this.reference = new WeakReference(reference);
hash = reference.GetHashCode();
}
public WeakReference reference;
public override bool Equals(object obj)
{
if (obj is WeakNode n)
{
n.reference.TryGetTarget(out INotifyPropertyChanged t1);
reference.TryGetTarget(out INotifyPropertyChanged t2);
if (t1 == null)
{
return t1 == t2;
}
return t1.Equals(t2);
}
return false;
}
readonly int hash;
public override int GetHashCode()
{
//if (hash == 0 && reference.TryGetTarget(out INotifyPropertyChanged t))
//{
// hash = t.GetHashCode();
// return hash;
//}
return hash;
}
}
CpfObject owner;
///
/// Target对象
///
public CpfObject Owner
{
get { return owner; }
internal set
{
//if (value == null && !unbind)
//{
// throw new Exception("错误");
//}
owner = value;
}
}
///
/// 数据源对象
///
public WeakReference Source { get; internal set; }
internal Binding(object sObj, string sourcePropertyName, string targetPropertyName, BindingMode bindingMode)
{
if (sObj != null)
{
Source = new WeakReference(sObj);
IsDataContext = false;
}
TargetPropertyName = targetPropertyName;
SourcePropertyName = sourcePropertyName;
BindingMode = bindingMode;
}
internal Binding() { }
///
/// 多级绑定的属性集合
///
string[] sourcePropertyNames;
internal bool IsDataContext = true;
string sourcePropertyName;
///
/// 数据源字段名
///
public string SourcePropertyName
{
get { return sourcePropertyName; }
internal set
{
sourcePropertyName = value;
if (value != null)
{
sourcePropertyNames = SourcePropertyName.Split('.');
}
else
{
sourcePropertyNames = null;
}
}
}
///
/// 链式绑定下标
///
public int SourcePropertyIndex
{
get;
internal set;
} = 0;
///
/// Owner被绑定的属性名
///
public string TargetPropertyName
{
get;
internal set;
}
///
/// SourceToTarget异常回调
///
public Action SourceToTargetError { get; set; }
///
/// TargetToSource异常回调
///
public Action TargetToSourceError { get; set; }
///
/// 数据绑定的转换
///
public Func