/// <summary> /// Gets the MetadataModel at the specified property name. /// </summary> /// <param name="propertyName">The property name of the MetadataModel to get.</param> /// <returns>The MetadataModel at the specified property name.</returns> public MetadataModel GetProperty(string propertyName) { if (!this.IsValueType) { if (string.IsNullOrWhiteSpace(propertyName)) { return(this); } if (!propertyName.Contains('.')) { if (!propertyName.EndsWith("]")) { return(this[propertyName]); } else { int propertyNameIndex = propertyName.LastIndexOf("["); string propertyIndexerName = propertyName.Substring(0, propertyNameIndex); int index = int.Parse(propertyName.Substring(propertyNameIndex, propertyName.Length - propertyNameIndex).Trim('[', ']')); return(this.GetProperty(propertyIndexerName)[index]); } } else { var propertyChain = propertyName.Trim().Split('.'); MetadataModel result = this; foreach (var item in propertyChain) { result = result.GetProperty(item); if (result == null) { break; } } return(result); } } else if (this.Name == propertyName) { return(this); } else { throw new InvalidOperationException(string.Format("This MetadataModel (Name: {0}) is a value type. Cannot access MetadataModel Properties.", this.Name ?? string.Empty)); } }
/// <summary> /// Adds the MetadataModel to the end of the Properties. /// </summary> /// <param name="property">The property to be added.</param> public void AddProperty(MetadataModel property) { if (!this.IsValueType) { if (this.Properties == null) { this.Properties = new List <MetadataModel>(); } this.Properties.Add(property); } else { throw new InvalidOperationException(string.Format("This MetadataModel (Name: {0}) is a value type. Cannot access MetadataModel Properties.", this.Name ?? string.Empty)); } }
/// <summary> /// Gets or sets the MetadataModel at the specified index. /// </summary> /// <param name="index">The zero-based index of the MetadataModel to get or set.</param> /// <returns>The MetadataModel at the specified index.</returns> public MetadataModel this[int index] { get { if (!this.IsValueType) { return(this.Properties[index]); } else { throw new InvalidOperationException("This MetadataModel is a value type. Cannot access MetadataModel Properties."); } } set { if (!this.IsValueType) { if (this.Properties == null) { this.Properties = new List <MetadataModel>(); } int count = this.Properties.Count; if (index > count - 1) { for (int i = 0; i <= index - count; i++) { this.Properties.Add(MetadataModel.GetEmptyMetadataModel()); } } this.Properties[index].CloneFrom(value, false); } else { throw new InvalidOperationException("This MetadataModel is a value type. Cannot access MetadataModel Properties."); } } }
/// <summary> /// Clone target MetadataModel to current MetadataModel. /// </summary> /// <param name="source">Current MetadataModel.</param> /// <param name="sourceModel">Target MetadataModel.</param> /// <param name="includeName">true if want to include Metadata name; otherwise, false.</param> /// <returns>The current MetadataModel.</returns> public static MetadataModel CloneFrom(this MetadataModel source, MetadataModel sourceModel, bool includeName = false) { if (sourceModel == null) { source.Value = null; source.Properties = null; } else { if (includeName) { source.Name = sourceModel.Name; } source.IsValueType = sourceModel.IsValueType; source.Value = sourceModel.Value; source.Properties = CloneDeep(sourceModel.Properties) as List <MetadataModel>; } return(source); }
/// <summary> /// Clone current MetadataModel to target MetadataModel. /// </summary> /// <param name="source">Current MetadataModel.</param> /// <param name="destModel">Destination MetadataModel.</param> /// <param name="includeName">true if want to include Metadata name; otherwise, false.</param> /// <returns>The destination MetadataModel.</returns> public static MetadataModel CloneTo(this MetadataModel source, MetadataModel destModel, bool includeName = false) { if (source == null) { destModel.Value = null; destModel.Properties = null; } else { if (includeName) { destModel.Name = source.Name; } destModel.IsValueType = source.IsValueType; destModel.Value = source.Value; destModel.Properties = CloneDeep(source.Properties) as List <MetadataModel>; } return(destModel); }
/// <summary> /// Convert MetadataModel instance to object. /// </summary> /// <typeparam name="T">The type of return object.</typeparam> /// <param name="source">MetadataModel to convert.</param> /// <returns>The target type object.</returns> public static T ToObject <T>(this MetadataModel <T> source) { return((T)source.ToObject(typeof(T))); }
/// <summary> /// Convert object to MetadataModel instance. /// </summary> /// <param name="source">Object to convert.</param> /// <param name="sourceType">The type of source object.</param> /// <param name="name">Name for result MetadataModel.</param> /// <returns>Instance of MetadataModel.</returns> public static MetadataModel ToMetadataModel(this object source, Type sourceType, string name = null) { if (source == null) { return(MetadataModel.GetEmptyMetadataModel()); } if (sourceType.Equals(typeof(MetadataModel))) { return((source as MetadataModel) ?? MetadataModel.GetEmptyMetadataModel()); } MetadataModel result = new MetadataModel { Name = name ?? sourceType.FullName.Replace('.', '_') }; if (XmlConverter.CanConvert(sourceType)) { result.IsValueType = true; try { result.Value = XmlConverter.ToString(source); } catch { result.Value = null; } } else if (source is XmlElement) { result.IsValueType = true; try { result.Value = (source as XmlElement).OuterXml; } catch { result.Value = null; } } else { result.IsValueType = false; if (CanEnumerable(sourceType)) { if (source != null) { foreach (var item in source as IEnumerable) { result.AddProperty(item.ToMetadataModel(item.GetType())); } } else { Type elementType = null; if (IsDictionary(sourceType)) { elementType = typeof(KeyValuePair <,>).MakeGenericType(sourceType.GetGenericArguments()); } else { elementType = sourceType.IsArray ? sourceType.GetElementType() : sourceType.GetGenericArguments()[0]; } result.AddProperty(((object)null).ToMetadataModel(elementType)); } } else { foreach (var item in sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanRead)) { try { object itemValue = source == null ? null : item.GetValue(source, null); result.AddProperty(itemValue.ToMetadataModel(item.PropertyType, item.Name)); } catch { } } } } return(result); }
/// <summary> /// Convert MetadataModel instance to object. /// </summary> /// <param name="source">MetadataModel to convert.</param> /// <param name="targetType">The type of return object.</param> /// <returns>The target type object.</returns> public static object ToObject(this MetadataModel source, Type targetType) { if (source.IsNull) { return(null); } if (targetType.Equals(typeof(MetadataModel))) { return(source); } if (XmlConverter.CanConvert(targetType)) { if (source.IsValueType && source.Value != null) { return(XmlConverter.ToObject(source.Value, targetType)); } else { return(null); } } else if (targetType.Equals(typeof(XmlElement))) { if (source.IsValueType && source.Value != null) { try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(source.Value); return(xmlDocument.DocumentElement); } catch { return(null); } } else { return(null); } } else { if (CanEnumerable(targetType)) { if (IsDictionary(targetType)) { IDictionary propertyDict = (IDictionary)Activator.CreateInstance(targetType, true); foreach (var propertyItem in source.Properties) { if (!propertyItem.IsNull) { try { var key = propertyItem[0].ToObject(targetType.GetGenericArguments()[0]); if (key != null) { var value = propertyItem[1].ToObject(targetType.GetGenericArguments()[1]); propertyDict.Add(key, value); } } catch { } } } return(propertyDict.Count > 0 ? propertyDict : (IDictionary)null); } else { if (targetType.IsArray) { Type elementType = targetType.GetElementType(); IList resultTemp = new List <dynamic>(); foreach (var propertyItem in source.Properties) { if (!propertyItem.IsNull) { try { var listItem = propertyItem.ToObject(elementType); if (listItem != null) { resultTemp.Add(listItem); } } catch { } } } if (resultTemp.Count > 0) { Array result = Array.CreateInstance(elementType, resultTemp.Count); resultTemp.CopyTo(result, 0); return(result); } else { return((IList)null); } } else { Type elementType = targetType.GetGenericArguments()[0]; IList result = (IList)Activator.CreateInstance(targetType, true); foreach (var propertyItem in source.Properties) { if (!propertyItem.IsNull) { try { var listItem = propertyItem.ToObject(elementType); if (listItem != null) { result.Add(listItem); } } catch { } } } return(result.Count > 0 ? result : (IList)null); } } } else { object result = null; try { result = Activator.CreateInstance(targetType, true); } catch { try { result = FormatterServices.GetUninitializedObject(targetType); } catch { } } if (result == null) { return(result); } bool isNullReturn = true; foreach (var item in targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(i => i.CanWrite)) { try { if (source.HasProperty(item.Name)) { var sourceItem = source.GetProperty(item.Name); var sourceItemValue = sourceItem.ToObject(item.PropertyType); item.SetValue(result, sourceItemValue, null); if (sourceItemValue != null) { isNullReturn = false; } } } catch { } } return(isNullReturn ? null : result); } } }
/// <summary> /// Sets the MetadataModel at the specified property name. /// </summary> /// <typeparam name="T">The type of the object who contains the property.</typeparam> /// <param name="propertyExpression">The property expression.</param> /// <param name="property">The instance of the property.</param> public void SetProperty <T>(Expression <Func <T, object> > propertyExpression, MetadataModel property) { this.SetProperty(propertyExpression.ExtractPropertyName <T>(), property); }
/// <summary> /// Sets the MetadataModel at the specified property name. /// </summary> /// <param name="propertyName">The property name of the MetadataModel to set.</param> /// <param name="property">The instance of the property.</param> public void SetProperty(string propertyName, MetadataModel property) { if (!this.IsValueType) { if (!propertyName.Contains('.')) { if (!propertyName.EndsWith("]")) { this[propertyName] = property; } else { int propertyNameIndex = propertyName.LastIndexOf("["); string propertyIndexerName = propertyName.Substring(0, propertyNameIndex); int index = int.Parse(propertyName.Substring(propertyNameIndex, propertyName.Length - propertyNameIndex).Trim('[', ']')); MetadataModel result = this; try { if (result.Properties != null && result.Properties.Count > 0 && result.Properties.Any(p => p.Name.Equals(propertyIndexerName))) { result = result.GetProperty(propertyIndexerName); } else { result.SetProperty(propertyIndexerName, new MetadataModel { Name = propertyIndexerName, IsValueType = false }); result = result.GetProperty(propertyIndexerName); } } catch { result.SetProperty(propertyIndexerName, new MetadataModel { Name = propertyIndexerName, IsValueType = false }); result = result.GetProperty(propertyIndexerName); } result[index] = property; } } else { var propertyChain = propertyName.Trim().Split('.'); MetadataModel result = this; foreach (var item in propertyChain) { try { if (result.Properties != null && result.Properties.Count > 0) { string itemName = item; if (item.EndsWith("]")) { int itemNameIndex = item.LastIndexOf("["); string itemIndexerName = item.Substring(0, itemNameIndex); itemName = itemIndexerName; } if (result.Properties.Any(p => p.Name.Equals(itemName)) || itemName == string.Empty) { result = result.GetProperty(item); continue; } } result.SetProperty(item, new MetadataModel { Name = item, IsValueType = false }); result = result.GetProperty(item); } catch { result.SetProperty(item, new MetadataModel { Name = item, IsValueType = false }); result = result.GetProperty(item); } } result.CloneFrom(property); } } else if (this.Name == propertyName) { this.Value = property.Value; } else { throw new InvalidOperationException(string.Format("This MetadataModel (Name: {0}) is a value type. Cannot access MetadataModel Properties.", this.Name ?? string.Empty)); } }
/// <summary> /// Determines whether the MetadataModel has the specified property. /// </summary> /// <param name="propertyName">Name of the property.</param> /// <returns>true if the MetadataModel has the specified property; otherwise, false.</returns> public bool HasProperty(string propertyName) { if (!this.IsValueType) { if (!propertyName.Contains('.')) { if (this.Properties != null && this.Properties.Count > 0) { string itemName = propertyName; if (propertyName.EndsWith("]")) { int itemNameIndex = propertyName.LastIndexOf("["); string itemIndexerName = propertyName.Substring(0, itemNameIndex); itemName = itemIndexerName; } return(this.Properties.Any(p => p.Name.Equals(itemName))); } return(false); } else { var propertyChain = propertyName.Trim().Split('.'); MetadataModel result = this; foreach (var item in propertyChain) { try { if (result.Properties != null && result.Properties.Count > 0) { string itemName = item; if (item.EndsWith("]")) { int itemNameIndex = item.LastIndexOf("["); string itemIndexerName = item.Substring(0, itemNameIndex); itemName = itemIndexerName; } if (result.Properties.Any(p => p.Name.Equals(itemName))) { result = result.GetProperty(item); continue; } } return(false); } catch { return(false); } } return(true); } } else { throw new InvalidOperationException(string.Format("This MetadataModel (Name: {0}) is a value type. Cannot access MetadataModel Properties.", this.Name ?? string.Empty)); } }