using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace InABox.Core { public class StandardProperty : IProperty { public Type _class; private Func _getter; private string _name = ""; private Action _setter; private bool _checkedExpressions; public string _type = ""; public Type _propertyType = typeof(object); public StandardProperty() { Editor = new NullEditor(); HasEditor = false; } public string Class { get => _class.EntityName(); set { _class = CoreUtils.GetEntity(value); ClearExpressions(); } } public Type? ClassType { get => _class; set { _class = value ?? typeof(object); } } public string Name { get => _name; set { _name = value; ClearExpressions(); } } public string Type { get => _type; set { Type propType; try { propType = CoreUtils.GetEntityOrNull(_type) ?? typeof(object); } catch { propType = typeof(object); } PropertyType = propType; // Invoke other setter to ensure consistency of functionality } } public Type PropertyType { get => _propertyType; set { _propertyType = value; _type = value.EntityName(); IsEntityLink = _propertyType.HasInterface(typeof(IEntityLink)); IsEnclosedEntity = _propertyType.HasInterface(typeof(IEnclosedEntity)); IsParent = IsEnclosedEntity || IsEntityLink; } } public PropertyInfo Property { get; set; } //[ComboLookupEditor(typeof(PropertyEditorLookups))] public BaseEditor Editor { get; set; } public bool HasEditor { get; set; } public string Caption { get; set; } private decimal _propertySequence; private long _sequence; public long Sequence { get => _sequence; set { _sequence = value; _propertySequence = CalculatePropertySequence(); } } [NullEditor] public string Page { get; set; } public bool Required { get; set; } public LoggablePropertyAttribute? Loggable { get; set; } private IProperty? _parent; public IProperty? Parent { get => _parent; set { _parent = value; _propertySequence = CalculatePropertySequence(); } } public bool IsEntityLink { get; set; } public bool IsEnclosedEntity { get; set; } public bool IsParent { get; set; } private bool? _calculated; public bool IsCalculated { get { if (!_calculated.HasValue) { _calculated = Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || this.GetParent(x => x.IsCalculated) != null; } return _calculated.Value; } } private bool IsPersistable(StandardProperty? prop) { if (prop == null) return true; if (prop.Property.GetCustomAttribute() != null) return false; return IsPersistable(prop.Parent as StandardProperty); } private bool? _dbColumn; public bool IsDBColumn { get { if (!_dbColumn.HasValue) { _dbColumn = !IsCalculated && IsPersistable(this) && Property.CanWrite; } return _dbColumn.Value; } } public TAttribute? GetAttribute() where TAttribute : Attribute { return Property.GetCustomAttribute(); } public Expression Expression() { return CoreUtils.CreateMemberExpression(_class, Name); } public Func Getter() { if (_getter is null) CheckExpressions(); return _getter; } public Action Setter() { if (_setter is null) CheckExpressions(); return _setter; } public decimal PropertySequence() => _propertySequence; private decimal CalculatePropertySequence() { var sequence = 0.0M; IProperty? property = this; while(property != null) { sequence = property.Sequence + sequence / 1000.0M; property = property.Parent; } return sequence; } public override string ToString() { return string.Format("{0}.{1}", Class, Name); } private void ClearExpressions() { _checkedExpressions = false; _getter = null; _setter = null; } private void CheckExpressions() { if(_checkedExpressions) return; if (_class == null) return; if (string.IsNullOrEmpty(_name)) return; try { _getter = Expressions.Getter(_class, _name); } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } try { _setter = Expressions.Setter(_class, _name); } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } _checkedExpressions = true; } } }