using Newtonsoft.Json; using System; using System.Linq; using System.Linq.Expressions; using System.Runtime.InteropServices; namespace InABox.Core { [UserTracking(typeof(User))] public class CustomProperty : Entity, IProperty, IPersistent, IRemotable, ISequenceable, ILicense { public Type? _class; private Func _getter; private string _name = ""; private Action _setter; private string _type; private Type type = typeof(object); private string _caption; private long _sequence; private string _page; private bool _visible; private bool _editable; protected override void Init() { base.Init(); Visible = true; Editable = true; Required = false; HasEditor = true; Editor = new NullEditor(); } [MemoEditor(Visible = Core.Visible.Default)] [EditorSequence(5)] public string Comment { get; set; } [CheckBoxEditor(Visible = Core.Visible.Default)] [EditorSequence(8)] public bool Visible { get => _visible; set { _visible = value; RegenerateEditor(); } } [CheckBoxEditor(Visible = Core.Visible.Optional)] [EditorSequence(9)] public bool Editable { get => _editable; set { _editable = value; RegenerateEditor(); } } [ComboLookupEditor(typeof(PropertyClassLookups))] [EditorSequence(1)] public string Class { get => _class != null ? _class.EntityName() : ""; set { CoreUtils.TryGetEntity(value, out _class); CheckExpressions(); } } [DoNotPersist] [DoNotSerialize] public Type? ClassType { get => _class; set { _class = value; CheckExpressions(); } } [EditorSequence(2)] public string Name { get => _name; set { _name = value; CheckExpressions(); RegenerateEditor(); } } [ComboLookupEditor(typeof(PropertyTypeLookups), Visible = Core.Visible.Default)] [EditorSequence(3)] public string Type { get => _type; set { _type = value; try { type = CoreUtils.GetEntityOrNull(_type) ?? typeof(object); } catch { type = typeof(object); } CheckExpressions(); IsEntityLink = type.GetInterfaces().Contains(typeof(IEntityLink)); IsEnclosedEntity = type.GetInterfaces().Contains(typeof(IEnclosedEntity)); RegenerateEditor(); } } [DoNotPersist] [DoNotSerialize] public Type PropertyType { get => type; set { type = value; _type = value.EntityName(); Editor = null; IsEntityLink = type.GetInterfaces().Contains(typeof(IEntityLink)); IsEnclosedEntity = type.GetInterfaces().Contains(typeof(IEnclosedEntity)); RegenerateEditor(); } } [NullEditor] [DoNotPersist] [DoNotSerialize] public BaseEditor Editor { get; set; } [NullEditor] [DoNotPersist] [DoNotSerialize] public bool HasEditor { get; set; } [TextBoxEditor(Visible = Core.Visible.Optional)] [EditorSequence(6)] public string Caption { get => _caption; set { _caption = value; RegenerateEditor(); } } [TextBoxEditor(Visible = Core.Visible.Optional)] [EditorSequence(7)] public string Page { get => _page; set { _page = value; RegenerateEditor(); } } [CheckBoxEditor(Visible = Core.Visible.Optional)] [EditorSequence(8)] public bool Required { get; set; } [NullEditor] [EditorSequence(9)] public LoggablePropertyAttribute? Loggable { get; set; } [NullEditor] public long Sequence { get => _sequence; set { _sequence = value; RegenerateEditor(); } } [NullEditor] [DoNotPersist] [DoNotSerialize] public IProperty? Parent { get; set; } [NullEditor] [DoNotPersist] [DoNotSerialize] public bool IsEntityLink { get; set; } [NullEditor] [DoNotPersist] [DoNotSerialize] public bool IsEnclosedEntity { get; set; } [NullEditor] [DoNotPersist] [DoNotSerialize] public bool IsCalculated => false; private static string? NonWhiteSpaceOrNull(string? name) { return string.IsNullOrWhiteSpace(name) ? null : name; } public TAttribute? GetAttribute() where TAttribute : Attribute { return null; } private void RegenerateEditor() { Editor = EditorUtils.GetEditor(PropertyType) ?? new NullEditor(); Editor.Caption = NonWhiteSpaceOrNull(Caption) ?? NonWhiteSpaceOrNull(Name) ?? ""; Editor.EditorSequence = (int)Sequence; Editor.Page = Page; Editor.Editable = Editable ? Core.Editable.Enabled : Core.Editable.Disabled; Editor.Visible = Visible ? Core.Visible.Optional : Core.Visible.Hidden; } public Expression Expression() { if (_class is null) throw new Exception("No class for CustomProperty"); return CoreUtils.CreateIndexExpression(_class, "UserProperties", Name); } public Func Getter() { return _getter; } public Action Setter() { return _setter; } public override string ToString() { return string.Format("{0}.{1}", Class, Name); } private void CheckExpressions() { if (_class == null) return; if (string.IsNullOrEmpty(Name)) return; try { _getter = Expressions.Getter(_class, "UserProperties", Name); _setter = Expressions.Setter(_class, "UserProperties", Name); } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } } public decimal PropertySequence() => Sequence; } public class CustomPropertyLookups : EntityLookup { public override Columns DefineColumns() { return base.DefineColumns() .Add(x => x.Class) .Add(x => x.Name); } //public string FormatLookup(Dictionary values, IEnumerable exclude) //{ // return LookupFactory.DefaultFormatLookup(values, exclude.Concat(new String[] { "ID" })); //} public override Filter? DefineFilter() { return null; } public override SortOrder DefineSortOrder() { return new SortOrder(x => x.Class).ThenBy(x => x.Sequence); } } }