/// <summary> /// Save an object in the source object's extension dictionary. /// </summary> /// <typeparam name="T">The type of the object to store.</typeparam> /// <param name="source">The source object to write the object to.</param> /// <param name="key">A string that acts as the key in the extension dictionary.</param> /// <param name="data">The object to store.</param> /// <exception cref="System.Exception">Thrown when an AutoCAD error occurs.</exception> public static void SaveData <T>(this DBObject source, string key, T data) { Require.ParameterNotNull(source, nameof(source)); void saveData(ResultBuffer buffer) { if (!source.IsWriteEnabled) { source.UpgradeOpen(); } if (source.ExtensionDictionary.IsNull) { source.CreateExtensionDictionary(); } Helpers.WrapInTransaction(source, tr => { var dict = (DBDictionary)tr.GetObject(source.ExtensionDictionary, OpenMode.ForWrite); if (dict.Contains(key)) { var xRecord = (Xrecord)tr.GetObject(dict.GetAt(key), OpenMode.ForWrite); xRecord.Data = buffer; } else { var xRecord = new Xrecord(); xRecord.Data = buffer; dict.SetAt(key, xRecord); tr.AddNewlyCreatedDBObject(xRecord, true); } }); } ResultBuffer getResultBuffer(DxfCode code) => new ResultBuffer(new[] { new TypedValue((int)code, data) }); // TODO: Add further types if (typeof(T) == typeof(bool)) { saveData(getResultBuffer(DxfCode.Bool)); } else if (typeof(T) == typeof(double)) { saveData(getResultBuffer(DxfCode.Real)); } else if (typeof(T) == typeof(byte)) { saveData(getResultBuffer(DxfCode.Int8)); } else if (typeof(T) == typeof(char) || typeof(T) == typeof(short)) { saveData(getResultBuffer(DxfCode.Int16)); } else if (typeof(T) == typeof(int)) { saveData(getResultBuffer(DxfCode.Int32)); } else if (typeof(T) == typeof(long)) { saveData(getResultBuffer(DxfCode.Int64)); } else if (typeof(T) == typeof(string)) { saveData(getResultBuffer(DxfCode.Text)); } else { saveData(new ResultBuffer(Helpers.Serialize(data) .Select(a => new TypedValue((int)DxfCode.BinaryChunk, a)) .ToArray())); } }
/// <summary> /// Reads an object from the source object's XData. /// </summary> /// <typeparam name="T">The type of the object to read.</typeparam> /// <param name="source">The source object to read the object from.</param> /// <param name="regAppName">The name of the RegApp to read the data from.</param> /// <exception cref="System.Exception">Thrown when an AutoCAD error occurs.</exception> /// <returns>The object in the extension dictionary.</returns> private static T GetFromXData <T>(DBObject source, string regAppName) { var resultBuffer = source.GetXDataForApplication(regAppName); Require.ObjectNotNull(resultBuffer, $"RegApp '{regAppName}' not found"); using (resultBuffer) { var xData = resultBuffer.Cast <TypedValue>() .Skip(1) .ToArray(); var targetType = typeof(T); var enumerable = typeof(T).GetInterface(typeof(IEnumerable <>).Name); if (typeof(T).Equals(typeof(string))) { enumerable = null; } else if (enumerable != null) { targetType = enumerable.GenericTypeArguments .FirstOrDefault(); } var tmpValues = new List <object>(); CollectValues(xData, tmpValues, targetType); var values = tmpValues.ToArray(); if (values.Length == 1 && values[0] is object[]) { values = values[0] as object[]; } if (enumerable != null) { if (targetType == typeof(object)) { return((T)(object)values); } else { var newValues = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(targetType)); foreach (var value in values) { if (typeof(T).Equals(typeof(Vector3d))) { var tmp = (Point3d)value; newValues.Add(new Vector3d(tmp.X, tmp.Y, tmp.Z)); } else { newValues.Add(value); } } return((T)newValues); } } else if (values.Length == 1) { return((T)values[0]); } else { if (typeof(T).Equals(typeof(object))) { return((T)(object)values); } else { throw new Exception("XData contains multiple: " + values.GetType().Name + " cannot be converted to " + typeof(T).Name); } } } }