using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Runtime.CompilerServices;
using System.Reflection;
using CPF.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.Diagnostics;
using CPF.Styling;
using CPF.Animation;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Collections;
namespace CPF
{
///
/// 默认所有属性都是依赖属性,如果不想作为依赖属性,属性上加上[NotCpfProperty]特性。不能使用new来覆盖已经定义为依赖属性的属性,最多255个依赖属性
///
public class CpfObject : INotifyPropertyChanged, IDisposable, ICloneable, Design.ISerializerCode, IObservable>
{
static ConcurrentDictionary> typeCache = new ConcurrentDictionary>();
static ConcurrentDictionary typePropertyCache = new ConcurrentDictionary();
static ConcurrentDictionary> inheritsProperties = new ConcurrentDictionary>();
static Dictionary> propertyChangedMethods = new Dictionary>();
static KeyValuePair>[] saveTypeCache;
static KeyValuePair[] saveTypePropertyCache;
static KeyValuePair>[] saveInheritsProperties;
static KeyValuePair>[] savePropertyChangedMethods;
public static void SetTypeCache()
{
saveTypeCache = typeCache.ToArray();
saveTypePropertyCache = typePropertyCache.ToArray();
saveInheritsProperties = inheritsProperties.ToArray();
FastReflectionExtensions.SetTypeCache();
savePropertyChangedMethods = propertyChangedMethods.ToArray();
}
public static void RecoveryTypeCache()
{
if (saveTypeCache != null)
{
typeCache.Clear();
foreach (var item in saveTypeCache)
{
typeCache.TryAdd(item.Key, item.Value);
}
saveTypeCache = null;
}
if (saveTypePropertyCache != null)
{
typePropertyCache.Clear();
foreach (var item in saveTypePropertyCache)
{
typePropertyCache.TryAdd(item.Key, item.Value);
}
saveTypePropertyCache = null;
}
if (saveInheritsProperties != null)
{
inheritsProperties.Clear();
foreach (var item in saveInheritsProperties)
{
inheritsProperties.TryAdd(item.Key, item.Value);
}
saveInheritsProperties = null;
}
if (savePropertyChangedMethods != null)
{
propertyChangedMethods.Clear();
foreach (var item in savePropertyChangedMethods)
{
propertyChangedMethods.Add(item.Key, item.Value);
}
savePropertyChangedMethods = null;
}
FastReflectionExtensions.RecoveryTypeCache();
}
Dictionary objInfo;
PropertyMetadataAttribute[] propertyInfos;
//EffectiveValue[] values;
byte[] valueIndexs;
_List valueList = new _List();
internal HybridDictionary attachedValues;
///
/// 继承属性的特性
///
internal HashSet inheritsPropertyName;
AttachedProperties attached;
///
/// 用于设置附加属性,和绑定附加属性
///
[Category("绑定")]
[Description("用于设置附加属性,一般控件上会有附加属性分组,那边设置就行,可以不需要在这里设置。")]
[NotCpfProperty]
public AttachedProperties Attacheds
{
get
{
if (attached == null)
{
attached = new AttachedProperties(this);
}
return attached;
}
}
AttachedNotify attachedNotify;
internal AttachedNotify AttachedNotify
{
get
{
if (attachedNotify == null)
{
attachedNotify = new AttachedNotify(this);
}
return attachedNotify;
}
}
internal Bindings bindings;
///
/// 设置绑定
///
[NotCpfProperty]
[Category("绑定")]
[Description("设置数据绑定")]
public Bindings Bindings
{
get
{
if (bindings == null)
{
bindings = new Bindings(this);
}
return bindings;
}
}
internal Commands commands;
///
/// 设置命令
///
[NotCpfProperty]
[Category("绑定")]
[Description("设置命令绑定")]
public Commands Commands
{
get
{
if (commands == null)
{
commands = new Commands(this);
}
return commands;
}
}
Type type;
///
/// 设置绑定
///
/// 需要绑定的属性名
///// 绑定的属性值转换到源对象的属性值
///
[NotCpfProperty]
public BindingDescribe this[string propertyName]
{
get { return new BindingDescribe { Source = this, PropertyName = propertyName }; }
set
{
Bindings.Add(propertyName, value.PropertyName, value.Source, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError);
}
}
public CpfObject()
{
type = this.GetType();
//Threading.Dispatcher.MainThread.VerifyAccess();
if (!typeCache.TryGetValue(type, out objInfo))
{
//typeNames.Add(type.Name, type);
objInfo = new Dictionary();
typeCache.TryAdd(type, objInfo);
List propertyList = new List();
var list = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
list = list.OrderBy(a => a.DeclaringType, new TypeCompar()).ThenBy(a => a.MetadataToken).ToArray();
OverrideMetadata om = new OverrideMetadata();
OnOverrideMetadata(om);
var not = typeof(NotCpfProperty);
var pm = typeof(PropertyMetadataAttribute);
var cm = typeof(ComputedAttribute);
byte id = 0;
//List<(PropertyInfo, ComputedAttribute[])> computeProterty = new List<(PropertyInfo, ComputedAttribute[])>();
List computeProterty = new List();
foreach (var item in list)
{
var nots = item.GetCustomAttributes(not, true);
if (nots.Length == 0)
{
var ass = item.GetCustomAttributes(pm, true);
PropertyMetadataAttribute a;
if (!om.list.TryGetValue(item.Name, out a))
{
if (ass.Length > 0)
{
a = (PropertyMetadataAttribute)ass[0];
}
else
{
a = new PropertyMetadataAttribute();
a.DefaultValue = item.PropertyType.IsValueType ? Activator.CreateInstance(item.PropertyType) : null; ;
}
}
a.PropertyType = item.PropertyType;
a.PropertyName = item.Name;
if (a.DefaultValue != null)
{
var t = a.DefaultValue.GetType();
if (t != a.PropertyType && !a.PropertyType.IsAssignableFrom(t))
{
throw new InvalidCastException($"{type.Name}的属性{item.Name}的默认值类型不对");
}
}
a.Id = id;
id++;
objInfo.Add(item.Name, a);
propertyList.Add(a);
var ca = item.GetCustomAttributes(cm, true);
if (ca.Length > 0)
{
//computeProterty.Add((item, (ComputedAttribute[])ca));
computeProterty.Add(new ComputeProtertyInfo { Property = item, NoticeProperties = ((ComputedAttribute[])ca)[0].Properties });
}
}
}
typePropertyCache.TryAdd(type, propertyList.ToArray());
var l = new HashSet();
foreach (var item in objInfo)
{
if (item.Value is UIPropertyMetadataAttribute attribute && attribute.Inherits)
{
l.Add(attribute.PropertyName);
}
}
if (l.Count == 0)
{
l = null;
}
inheritsProperties.TryAdd(type, l);
//Type tt = typeof(PropertyChangedAttribute);
//var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, (a, b) => a.CustomAttributes.Any(c => c.AttributeType == tt), null);
foreach (MethodInfo item in Methods(type))
{
try
{
var attrs = item.GetCustomAttributes(typeof(PropertyChangedAttribute), true);
foreach (PropertyChangedAttribute attr in attrs)
{
if (!objInfo.TryGetValue(attr.PropertyName, out PropertyMetadataAttribute attribute))
{
throw new Exception("不存在属性:" + attr.PropertyName);
}
if (attribute.actions == null)
{
attribute.actions = new List();
}
var instanceParameter = Expression.Parameter(typeof(CpfObject), "instance");
var newValueParameter = Expression.Parameter(typeof(object), "newValue");
var oldValueParameter = Expression.Parameter(typeof(object), "oldValue");
var attributeParameter = Expression.Parameter(typeof(PropertyMetadataAttribute), "attribute");
var instanceCast = Expression.Convert(instanceParameter, item.ReflectedType);
var methodCall = Expression.Call(instanceCast, item, new ParameterExpression[] { newValueParameter, oldValueParameter, attributeParameter });
var lambda = Expression.Lambda(
methodCall, instanceParameter, newValueParameter, oldValueParameter, attributeParameter);
var execute = lambda.Compile();
attribute.actions.Add(execute);
}
}
catch (Exception e)
{
throw new Exception("绑定属性通知出错,检查方法参数类型和返回值类型:" + item.Name, e);
}
}
OnInitializeComputeProterty(computeProterty.Where(a => a.NoticeProperties == null));
foreach (var item in computeProterty)
{
//if (item.Item2[0].Properties != null && item.Item2[0].Properties.Length > 0)
if (item.NoticeProperties == null && item.Tokens != null)
{
List ps = new List();
foreach (var t in item.Tokens)
{
var p = list.FirstOrDefault(a => a.MetadataToken == t);
if (p != null)
{
ps.Add(p.Name);
}
}
item.NoticeProperties = ps.ToArray();
}
if (item.NoticeProperties != null && item.NoticeProperties.Length > 0)
{
//foreach (var p in item.Item2[0].Properties)
foreach (var p in item.NoticeProperties)
{
if (!string.IsNullOrWhiteSpace(p))
{
if (!objInfo.TryGetValue(p, out PropertyMetadataAttribute attribute))
{
throw new Exception("不存在属性:" + p);
}
if (attribute.actions == null)
{
attribute.actions = new List();
}
var instanceParameter = Expression.Parameter(typeof(CpfObject), "instance");
var newValueParameter = Expression.Parameter(typeof(object), "newValue");
var oldValueParameter = Expression.Parameter(typeof(object), "oldValue");
var attributeParameter = Expression.Parameter(typeof(PropertyMetadataAttribute), "attribute");
//var instanceCast = Expression.Convert(instanceParameter, item.Item1.ReflectedType);
var instanceCast = Expression.Convert(instanceParameter, item.Property.ReflectedType);
var propValue = Expression.Property(instanceCast, item.Property);
var methodCall = Expression.Call(instanceCast, setValue.MakeGenericMethod(typeof(object)), propValue, Expression.Constant(item.Property.Name));
var lambda = Expression.Lambda(
methodCall, instanceParameter, newValueParameter, oldValueParameter, attributeParameter);
var execute = lambda.Compile();
attribute.actions.Add(execute);
}
}
}
}
}
//values = new EffectiveValue[objInfo.Count];
propertyInfos = typePropertyCache[type];
if (objInfo.Count > 255)
{
throw new Exception(type + "类型属性数量不能超过255");
}
//valueIndexs = new ByteArray((byte)objInfo.Count);
valueIndexs = new byte[objInfo.Count];
inheritsPropertyName = inheritsProperties[type];
}
class TypeCompar : IComparer
{
public int Compare(Type x, Type y)
{
if (x == y)
{
return 0;
}
if (x.IsAssignableFrom(y))
{
return -1;
}
return 1;
}
}
static MethodInfo setValue = typeof(CpfObject).GetMethod(nameof(SetValue));
static IEnumerable Methods(Type type)
{
if (!propertyChangedMethods.TryGetValue(type, out List methods))
{
methods = new List();
Type t = typeof(PropertyChangedAttribute);
//var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, (a, b) => a.CustomAttributes.Any(c => c.AttributeType == t), null);
var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, (a, b) =>
{
var alist = a.GetCustomAttributes(t, true);
return alist != null && alist.Length > 0;
}, null);
foreach (MethodInfo item in ms)
{
if (!item.IsStatic)
{
methods.Add(item);
}
}
propertyChangedMethods.Add(type, methods);
}
foreach (var item in methods)
{
yield return item;
}
if (type.BaseType != typeof(object))
{
foreach (var item in Methods(type.BaseType))
{
yield return item;
}
}
}
///
/// 用于初始化计算属性,请不要调用和重写,内部使用
///
///
protected virtual void OnInitializeComputeProterty(IEnumerable computeProterties)
{
//foreach (var item in computeProterties)
//{
// if (item.Property.Name == "通知属性1")
// {
// item.NoticeProperties = new string[] { "属性1", "属性2" };
// item.Tokens = new int[] { };//如果没有解析到属性名,NoticeProperties不要设置
// }
//}
}
///
/// 该类型的第一个对象构造的时候调用,重写属性元数据,一般重写属性的代码写在base.OnOverrideMetadata后面
///
///
protected virtual void OnOverrideMetadata(OverrideMetadata overridePropertys)
{
}
//[PropertyMetadata(null)]
//public string Name
//{
// get { return GetValue(); }
// set { SetValue(value); }
//}
///
/// 绑定的数据上下文
///
[Category("绑定")]
[Description("绑定的数据上下文")]
[UIPropertyMetadata(null, true)]
public virtual object DataContext
{
get { return GetValue