private PropertiesSnapshot GetSnapshot(IModelDoc2 model)
        {
            var snaphot = new PropertiesSnapshot()
            {
                Properties = new Dictionary <string, string>()
            };

            var prpMgr = model.Extension.CustomPropertyManager[""];

            var prpNames = prpMgr.GetNames() as string[];

            if (prpNames != null)
            {
                foreach (var prpName in prpNames)
                {
                    string val;
                    string resVal;
                    bool   wasRes;
                    prpMgr.Get5(prpName, false, out val, out resVal, out wasRes);
                    snaphot.Properties.Add(prpName, resVal);
                }
            }

            return(snaphot);
        }
        private async Task SaveSnapshotToDocument(IModelDoc2 model, PropertiesSnapshot data)
        {
            int err  = -1;
            int warn = -1;

            model.SetSaveFlag();

            const int S_OK = 0;

            bool?result = null;;

            var onSaveToStorageStoreNotifyFunc = new Func <int>(() =>
            {
                try
                {
                    StoreData(model, data, STORAGE_NAME, storage =>
                    {
                        string snapshotName = "";

                        AccessStreamFromPath(storage, SNAPSHOT_INFO_STREAM_NAME, true, true, stream =>
                        {
                            var ser = new DataContractSerializer(typeof(List <SnapshotInfo>));

                            List <SnapshotInfo> snapshotInfos = null;

                            if (stream.Length > 0)
                            {
                                snapshotInfos = ser.ReadObject(stream) as List <SnapshotInfo>;
                            }
                            else
                            {
                                snapshotInfos = new List <SnapshotInfo>();
                            }

                            var info = new SnapshotInfo()
                            {
                                Revision  = snapshotInfos.Count + 1,
                                TimeStamp = DateTime.Now
                            };

                            snapshotInfos.Add(info);

                            snapshotName = string.Format(SNAPSHOT_STREAM_NAME_TEMPLATE, info.Revision);

                            stream.Seek(0, System.IO.SeekOrigin.Begin);

                            ser.WriteObject(stream, snapshotInfos);
                        }, STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE);

                        AccessStreamFromPath(storage, snapshotName, true, true, stream =>
                        {
                            var ser = new DataContractSerializer(typeof(PropertiesSnapshot));
                            ser.WriteObject(stream, data);
                        }, STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE);

                        result = true;
                    });
                }
                catch
                {
                    result = false;
                }
                return(S_OK);
            });

            var partSaveToStorageNotify = new DPartDocEvents_SaveToStorageStoreNotifyEventHandler(onSaveToStorageStoreNotifyFunc);
            var assmSaveToStorageNotify = new DAssemblyDocEvents_SaveToStorageStoreNotifyEventHandler(onSaveToStorageStoreNotifyFunc);
            var drwSaveToStorageNotify  = new DDrawingDocEvents_SaveToStorageStoreNotifyEventHandler(onSaveToStorageStoreNotifyFunc);

            #region Attach Event Handlers

            switch ((swDocumentTypes_e)model.GetType())
            {
            case swDocumentTypes_e.swDocPART:
                (model as PartDoc).SaveToStorageStoreNotify += partSaveToStorageNotify;
                break;

            case swDocumentTypes_e.swDocASSEMBLY:
                (model as AssemblyDoc).SaveToStorageStoreNotify += assmSaveToStorageNotify;
                break;

            case swDocumentTypes_e.swDocDRAWING:
                (model as DrawingDoc).SaveToStorageStoreNotify += drwSaveToStorageNotify;
                break;
            }

            #endregion

            if (!model.Save3((int)swSaveAsOptions_e.swSaveAsOptions_Silent, ref err, ref warn))
            {
                throw new InvalidOperationException($"Failed to save the model: {(swFileSaveError_e)err}");
            }

            await Task.Run(() =>
            {
                while (!result.HasValue)
                {
                    System.Threading.Thread.Sleep(10);
                }
            });

            #region Detach Event Handlers

            switch ((swDocumentTypes_e)model.GetType())
            {
            case swDocumentTypes_e.swDocPART:
                (model as PartDoc).SaveToStorageStoreNotify -= partSaveToStorageNotify;
                break;

            case swDocumentTypes_e.swDocASSEMBLY:
                (model as AssemblyDoc).SaveToStorageStoreNotify -= assmSaveToStorageNotify;
                break;

            case swDocumentTypes_e.swDocDRAWING:
                (model as DrawingDoc).SaveToStorageStoreNotify -= drwSaveToStorageNotify;
                break;
            }

            #endregion

            if (!result.Value)
            {
                throw new Exception("Failed to store the data");
            }
        }