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 bool? _calculated; private Action _setter; public string _type = ""; public Type _propertyType = typeof(object); public StandardProperty() { Editor = new NullEditor(); HasEditor = false; } [ComboLookupEditor(typeof(StandardPropertyClassLookups))] public string Class { get => _class.EntityName(); set { _class = CoreUtils.GetEntity(value); CheckExpressions(); } } public Type? ClassType { get => _class; set { _class = value ?? typeof(object); } } public string Name { get => _name; set { _name = value; CheckExpressions(); } } [ComboLookupEditor(typeof(PropertyTypeLookups))] 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.GetInterfaces().Contains(typeof(IEntityLink)); IsEnclosedEntity = _propertyType.GetInterfaces().Contains(typeof(IEnclosedEntity)); } } 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 IsCalculated { get { if (!_calculated.HasValue) { _calculated = Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null || Property.GetCustomAttribute() != null; } return _calculated.Value; } } public TAttribute? GetAttribute() where TAttribute : Attribute { return Property.GetCustomAttribute(); } public Expression Expression() { return CoreUtils.CreateMemberExpression(_class, Name); } public Func Getter() { return _getter; } public Action Setter() { 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 CheckExpressions() { if (_class == null) return; if (string.IsNullOrEmpty(_name)) return; try { _propertyType = CoreUtils.GetProperty(_class, _name).PropertyType; } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } 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)); } } private class StandardPropertyClassLookups : LookupGenerator { public StandardPropertyClassLookups(object[] items) : base(items) { var types = CoreUtils.TypeList( AppDomain.CurrentDomain.GetAssemblies(), myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(BaseEditor)) ); foreach (var type in types) AddValue(type.EntityName(), type.Name); } } } }