private static void inheritAttribute(FieldAttribute parent, FieldAttribute self, string callSite) { //merge attributes from parent into self prop by prop foreach(var pi in ALL_PROPS) { if (pi.Name==nameof(MetadataContent)) { if (self.MetadataContent.IsNullOrWhiteSpace()) self.MetadataContent = parent.MetadataContent; else if (parent.MetadataContent.IsNotNullOrWhiteSpace()) { //merge var conf1 = ParseMetadataContent(parent.MetadataContent, callSite); var conf2 = ParseMetadataContent(self.MetadataContent, callSite); var merged = new LaconicConfiguration(); merged.CreateFromMerge(conf1, conf2); self.MetadataContent = merged.SaveToString(); } continue; }//metadata merge if (pi.Name==nameof(ValueList)) { if (!self.HasValueList) self.ValueList = parent.ValueList; else if (parent.HasValueList) { //merge var vl1 = parent.ParseValueList(true); var vl2 = self.ParseValueList(true); vl2.Append(vl1);//merge missing in self from parent //remove all that start with REMOVE // to remove a key include an override with: `keyABC: #del#` (item keyed on `keyABC` will be removed) const string DELETE = "#del#"; vl2.Where(kvp => kvp.Value.AsString().EqualsOrdIgnoreCase(DELETE)) .ToArray() .ForEach( kvp => vl2.Remove(kvp.Key) ); self.ValueList = BuildValueListString(vl2);//reconstitute jsonmap back into string } continue; } if (self.PropertyWasAssigned(pi.Name)) continue;//was overridden pi.SetValue(self, pi.GetValue(parent));//set value } }
public FieldAttribute( Type protoType, string protoFieldName, //Schema:Field string targetName = ANY_TARGET, object storeFlag = null, object key = null, object kind = null, object required = null, object visible = null, string valueList = null, object dflt = null, object min = null, object max = null, object minLength = null, object maxLength = null, object charCase = null, string backendName = null, string backendType = null, string description = null, string metadata = null, object nonUI = null, string formatRegExp = null, string formatDescr = null, string displayFormat = null, object isArow = null ) : base(targetName, null) { if (protoType == null || protoFieldName.IsNullOrWhiteSpace()) { throw new DataException(StringConsts.ARGUMENT_ERROR + "FieldAttr.ctor(protoType|protoFieldName=null|empty)"); } try { var schema = Schema.GetForTypedDoc(protoType); var protoTargetName = targetName; var segs = protoFieldName.Split(':'); if (segs.Length > 1) { protoTargetName = segs[0].Trim(); protoFieldName = segs[1].Trim(); } if (protoTargetName.IsNullOrWhiteSpace()) { throw new Exception("Wrong target syntax"); } if (protoFieldName.IsNullOrWhiteSpace()) { throw new Exception("Wrong field syntax"); } var protoFieldDef = schema[protoFieldName]; if (protoFieldDef == null) { throw new Exception("Prototype '{0}' field '{1}' not found".Args(protoType.FullName, protoFieldName)); } var protoAttr = protoFieldDef[protoTargetName]; try { StoreFlag = storeFlag == null? protoAttr.StoreFlag : (StoreFlag)storeFlag; BackendName = backendName == null? protoAttr.BackendName : backendName; BackendType = backendType == null? protoAttr.BackendType : backendType; Key = key == null? protoAttr.Key : (bool)key; Kind = kind == null? protoAttr.Kind : (DataKind)kind; Required = required == null? protoAttr.Required : (bool)required; Visible = visible == null? protoAttr.Visible : (bool)visible; Min = min == null? protoAttr.Min : min; Max = max == null? protoAttr.Max : max; Default = dflt == null? protoAttr.Default : dflt; MinLength = minLength == null? protoAttr.MinLength : (int)minLength; MaxLength = maxLength == null? protoAttr.MaxLength : (int)maxLength; CharCase = charCase == null? protoAttr.CharCase : (CharCase)charCase; ValueList = valueList == null? protoAttr.ValueList : valueList; Description = description == null? protoAttr.Description : description; NonUI = nonUI == null? protoAttr.NonUI : (bool)nonUI; FormatRegExp = formatRegExp == null? protoAttr.FormatRegExp: formatRegExp; FormatDescription = formatDescr == null? protoAttr.FormatDescription: formatDescr; DisplayFormat = displayFormat == null? protoAttr.DisplayFormat : displayFormat; IsArow = isArow == null? protoAttr.IsArow : (bool)isArow; if (metadata.IsNullOrWhiteSpace()) { m_MetadataContent = protoAttr.m_MetadataContent; } else if (protoAttr.m_MetadataContent.IsNullOrWhiteSpace()) { m_MetadataContent = metadata; } else { var conf1 = ParseMetadataContent(protoAttr.m_MetadataContent); var conf2 = ParseMetadataContent(metadata); var merged = new LaconicConfiguration(); merged.CreateFromMerge(conf1, conf2); m_MetadataContent = merged.SaveToString(); } } catch (Exception err) { throw new Exception("Invalid assignment of prototype override value: " + err.ToMessageWithType()); } } catch (Exception error) { throw new DataException(StringConsts.CRUD_FIELD_ATTR_PROTOTYPE_CTOR_ERROR.Args(error.Message)); } }