当前位置: 首页>>代码示例>>C#>>正文


C# StudyStorageLocation.GetStudyPath方法代码示例

本文整理汇总了C#中StudyStorageLocation.GetStudyPath方法的典型用法代码示例。如果您正苦于以下问题:C# StudyStorageLocation.GetStudyPath方法的具体用法?C# StudyStorageLocation.GetStudyPath怎么用?C# StudyStorageLocation.GetStudyPath使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在StudyStorageLocation的用法示例。


在下文中一共展示了StudyStorageLocation.GetStudyPath方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。

示例1: LoadInstance

		/// <summary>
		/// Load the first instance from the first series of the StudyXml file for a study.
		/// </summary>
		/// <param name="location">The storage location of the study.</param>
		/// <returns></returns>
		protected static DicomFile LoadInstance(StudyStorageLocation location)
		{
			string studyXml = Path.Combine(location.GetStudyPath(), location.StudyInstanceUid + ".xml");

			if (!File.Exists(studyXml))
			{
				return null;
			}

			FileStream stream = FileStreamOpener.OpenForRead(studyXml, FileMode.Open);
			var theDoc = new XmlDocument();
			StudyXmlIo.Read(theDoc, stream);
			stream.Close();
			stream.Dispose();
			var xml = new StudyXml();
			xml.SetMemento(theDoc);
            
			IEnumerator<SeriesXml> seriesEnumerator = xml.GetEnumerator();
			if (seriesEnumerator.MoveNext())
			{
				SeriesXml seriesXml = seriesEnumerator.Current;
				IEnumerator<InstanceXml> instanceEnumerator = seriesXml.GetEnumerator();
				if (instanceEnumerator.MoveNext())
				{
					InstanceXml instance = instanceEnumerator.Current;
					var file = new DicomFile("file.dcm",new DicomAttributeCollection(), instance.Collection)
						{TransferSyntax = instance.TransferSyntax};
					return file;
				}
			}

			return null;
		}
开发者ID:jfphilbin,项目名称:ClearCanvas,代码行数:38,代码来源:BaseReapplyRulesServiceLockItemProcessor.cs

示例2: SaveXmlCommand

        public SaveXmlCommand(StudyXml stream, StudyStorageLocation storageLocation)
            : base("Insert into Study XML", true)
        {
            Platform.CheckForNullReference(stream, "StudyStream object");
            Platform.CheckForNullReference(storageLocation, "Study Storage Location");

            _stream = stream;
            _xmlPath = Path.Combine(storageLocation.GetStudyPath(), storageLocation.StudyInstanceUid + ".xml");
            _gzPath = _xmlPath + ".gz";
        }
开发者ID:m-berkani,项目名称:ClearCanvas,代码行数:10,代码来源:SaveXmlCommand.cs

示例3: Load

 /// <summary>
 /// Loads the <see cref="Series"/> and instance mappings for the specified study.
 /// </summary>
 /// <param name="location"></param>
 public void Load(StudyStorageLocation location)
 {
     Load(Path.Combine(location.GetStudyPath(), "UidMap.xml"));
 }
开发者ID:nhannd,项目名称:Xian,代码行数:8,代码来源:UidMapXml.cs

示例4: ConvertToAbsolutePath

        /// <summary>
        /// Computes and returns the absolute path specified by this <see cref="FilesystemDynamicPath"/> for the <see cref="StudyStorageLocation"/>.
        /// Note: The path may or may not be valid.
        /// </summary>
        /// <param name="studyStorage"></param>
        /// <returns></returns>
        public string ConvertToAbsolutePath(StudyStorageLocation studyStorage)
        {
            switch (_type)
            {
                case PathType.Absolute: return _path;

                case PathType.RelativeToReconcileFolder:
                    var basePath = studyStorage.GetReconcileRootPath();
                    return Path.Combine(basePath, _path);

                case PathType.RelativeToStudyFolder:
                    basePath = studyStorage.GetStudyPath();
                    return Path.Combine(basePath, _path);

                default:
                    return _path;
            }
        }
开发者ID:m-berkani,项目名称:ClearCanvas,代码行数:24,代码来源:FilesystemDynamicPath.cs

示例5: LoadStudyXml

        /// <summary>
        /// Load a <see cref="StudyXml"/> file for a given <see cref="StudyStorageLocation"/>
        /// </summary>
        /// <param name="location">The location a study is stored.</param>
        /// <returns>The <see cref="StudyXml"/> instance for <paramref name="location"/></returns>
        protected virtual StudyXml LoadStudyXml(StudyStorageLocation location)
        {
            StudyXml theXml = new StudyXml();

            StudyXmlLoadTime.Add(
                delegate
                    {
                        String streamFile = Path.Combine(location.GetStudyPath(), location.StudyInstanceUid + ".xml");
                        if (File.Exists(streamFile))
                        {
                            using (Stream fileStream = FileStreamOpener.OpenForRead(streamFile, FileMode.Open))
                            {
                                XmlDocument theDoc = new XmlDocument();

                                StudyXmlIo.Read(theDoc, fileStream);

                                theXml.SetMemento(theDoc);

                                fileStream.Close();
                            }
                        }
                    }
                );

           return theXml;
        }
开发者ID:jfphilbin,项目名称:ClearCanvas,代码行数:31,代码来源:BaseItemProcessor.cs

示例6: DoMigrateStudy

        /// <summary>
        /// Migrates the study to new tier
        /// </summary>
        /// <param name="storage"></param>
        /// <param name="newFilesystem"></param>
        private void DoMigrateStudy(StudyStorageLocation storage, ServerFilesystemInfo newFilesystem)
        {
            Platform.CheckForNullReference(storage, "storage");
            Platform.CheckForNullReference(newFilesystem, "newFilesystem");

            TierMigrationStatistics stat = new TierMigrationStatistics {StudyInstanceUid = storage.StudyInstanceUid};
        	stat.ProcessSpeed.Start();
    	    StudyXml studyXml = storage.LoadStudyXml();
            stat.StudySize = (ulong) studyXml.GetStudySize(); 

            Platform.Log(LogLevel.Info, "About to migrate study {0} from {1} to {2}", 
                    storage.StudyInstanceUid, storage.FilesystemTierEnum, newFilesystem.Filesystem.Description);
			
            string newPath = Path.Combine(newFilesystem.Filesystem.FilesystemPath, storage.PartitionFolder);
    	    DateTime startTime = Platform.Time;
            DateTime lastLog = Platform.Time;
    	    int fileCounter = 0;
    	    ulong bytesCopied = 0;
    	    long instanceCountInXml = studyXml.NumberOfStudyRelatedInstances;
            
            using (ServerCommandProcessor processor = new ServerCommandProcessor("Migrate Study"))
            {
                TierMigrationContext context = new TierMigrationContext
                                               	{
                                               		OriginalStudyLocation = storage,
                                               		Destination = newFilesystem
                                               	};

            	string origFolder = context.OriginalStudyLocation.GetStudyPath();
                processor.AddCommand(new CreateDirectoryCommand(newPath));

                newPath = Path.Combine(newPath, context.OriginalStudyLocation.StudyFolder);
                processor.AddCommand(new CreateDirectoryCommand(newPath));

                newPath = Path.Combine(newPath, context.OriginalStudyLocation.StudyInstanceUid);
                // don't create this directory so that it won't be backed up by MoveDirectoryCommand

                CopyDirectoryCommand copyDirCommand = new CopyDirectoryCommand(origFolder, newPath, 
                    delegate (string path)
                        {
                            // Update the progress. This is useful if the migration takes long time to complete.

                            FileInfo file = new FileInfo(path);
                            bytesCopied += (ulong)file.Length;
                            fileCounter++;
                            if (file.Extension != null && file.Extension.Equals(ServerPlatform.DicomFileExtension, StringComparison.InvariantCultureIgnoreCase))
                            {
                                TimeSpan elapsed = Platform.Time - lastLog;
                                TimeSpan totalElapsed = Platform.Time - startTime;
                                double speedInMBPerSecond = 0;
                                if (totalElapsed.TotalSeconds > 0)
                                {
                                    speedInMBPerSecond = (bytesCopied / 1024f / 1024f) / totalElapsed.TotalSeconds;
                                }

                                if (elapsed > TimeSpan.FromSeconds(WorkQueueSettings.Instance.TierMigrationProgressUpdateInSeconds))
                                {
                                    #region Log Progress

                                    StringBuilder stats = new StringBuilder();
                                    if (instanceCountInXml != 0)
                                    {
                                        float pct = (float)fileCounter / instanceCountInXml;
                                        stats.AppendFormat("{0} files moved [{1:0.0}MB] since {2} ({3:0}% completed). Speed={4:0.00}MB/s",
                                                    fileCounter, bytesCopied / 1024f / 1024f, startTime, pct * 100, speedInMBPerSecond);
                                    }
                                    else
                                    {
                                        stats.AppendFormat("{0} files moved [{1:0.0}MB] since {2}. Speed={3:0.00}MB/s",
                                                    fileCounter, bytesCopied / 1024f / 1024f, startTime, speedInMBPerSecond);

                                    }

                                    Platform.Log(LogLevel.Info, "Tier migration for study {0}: {1}", storage.StudyInstanceUid, stats.ToString());
                                    try
                                    {
                                        using (IUpdateContext ctx = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                                        {
                                            IWorkQueueEntityBroker broker = ctx.GetBroker<IWorkQueueEntityBroker>();
                                            WorkQueueUpdateColumns parameters = new WorkQueueUpdateColumns
                                                                                	{FailureDescription = stats.ToString()};
                                        	broker.Update(WorkQueueItem.GetKey(), parameters);
                                            ctx.Commit();
                                        }
                                    }
                                    catch
                                    {
                                    	// can't log the progress so far... just ignore it
                                    }
                                    finally
                                    {
                                        lastLog = DateTime.Now;
                                    } 
                                    #endregion
                                }
//.........这里部分代码省略.........
开发者ID:nhannd,项目名称:Xian,代码行数:101,代码来源:TierMigrateItemProcessor.cs

示例7: Run

		/// <summary>
		/// Do the restore.
		/// </summary>
		/// <param name="queueItem">The queue item to restore.</param>
		public void Run(RestoreQueue queueItem)
		{
            using (RestoreProcessorContext context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _nasArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

                        StudyStorageLocationQueryParameters parms = new StudyStorageLocationQueryParameters
                                                                    	{StudyStorageKey = queueItem.StudyStorageKey};
                    	IQueryStudyStorageLocation broker = readContext.GetBroker<IQueryStudyStorageLocation>();
                        _location = broker.FindOne(parms);
                        if (_location == null)
                        {
                            _studyStorage = StudyStorage.Load(readContext, queueItem.StudyStorageKey);
							if (_studyStorage==null)
							{
								DateTime scheduleTime = Platform.Time.AddMinutes(5);
								Platform.Log(LogLevel.Error, "Unable to find storage location, rescheduling restore request to {0}",
											 scheduleTime);
								queueItem.FailureDescription = "Unable to find storage location, rescheduling request.";
								_nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
								return;
							}
                        }
                    }

					if (_location == null)
						Platform.Log(LogLevel.Info, "Starting restore of nearline study: {0}", _studyStorage.StudyInstanceUid);
					else
                        Platform.Log(LogLevel.Info, "Starting restore of online study: {0}", _location.StudyInstanceUid);

                    // If restoring a Nearline study, select a filesystem
                    string destinationFolder;
                    if (_location == null)
                    {
                        ServerFilesystemInfo fs = _nasArchive.Selector.SelectFilesystem();
                        if (fs == null)
                        {
                            DateTime scheduleTime = Platform.Time.AddMinutes(5);
                            Platform.Log(LogLevel.Error, "No writeable filesystem for restore, rescheduling restore request to {0}",
                                         scheduleTime);
                            queueItem.FailureDescription = "No writeable filesystem for restore, rescheduling request.";
                            _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
                            return;
                        }
                        destinationFolder = Path.Combine(fs.Filesystem.FilesystemPath, _nasArchive.ServerPartition.PartitionFolder);
                    }
                    else
                        destinationFolder = _location.GetStudyPath();


                    // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                    // Also store the "StudyFolder" for use below
                    string studyFolder = String.Empty;
                    string filename = String.Empty;
                    string studyInstanceUid = String.Empty;
                    XmlElement element = _archiveStudyStorage.ArchiveXml.DocumentElement;
					if (element!=null)
						foreach (XmlElement node in element.ChildNodes)
							if (node.Name.Equals("StudyFolder"))
								studyFolder = node.InnerText;
							else if (node.Name.Equals("Filename"))
								filename = node.InnerText;
							else if (node.Name.Equals("Uid"))
								studyInstanceUid = node.InnerText;

                    string zipFile = Path.Combine(_nasArchive.NasPath, studyFolder);
                    zipFile = Path.Combine(zipFile, studyInstanceUid);
                    zipFile = Path.Combine(zipFile, filename);


                    // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                    // fails, we just set back to pending and recheck.
                    try
                    {
                        FileStream stream = File.OpenRead(zipFile);
                        // Read a byte, just in case that makes a difference.
                        stream.ReadByte();
                        stream.Close();
                        stream.Dispose();
                    }
                    catch (Exception ex)
                    {
                        DateTime scheduledTime = Platform.Time.AddSeconds(NasSettings.Default.ReadFailRescheduleDelaySeconds);
                        Platform.Log(LogLevel.Error, ex, "Archive {0} for Study  {1} is unreadable, rescheduling restore to {2}",
                                     zipFile, _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                                     scheduledTime);
                        // Just reschedule in "Restoring" state, the file is unreadable.
                        _nasArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Restoring,
                                                       scheduledTime);
//.........这里部分代码省略.........
开发者ID:fparisotto,项目名称:ClearCanvas-Contrib,代码行数:101,代码来源:NasStudyRestore.cs

示例8: EstimateFolderSizeFromStudyXml

		/// <summary>
		/// Estimate the folder size for a study
		/// </summary>
		/// <remarks>
		/// This routine loads the StudyXml file and traverses through each series
		/// for the study.  It then looks at the size of the first image in the series,
		/// and assumes the series size is equal to the first image size times the number
		/// of images within the series.  If the file sizes vary within the series, this
		/// algorithm will fall down a bit.
		/// </remarks>
		/// <param name="location">The StudyStorageLocation object for the study.</param>
		/// <returns></returns>
		protected float EstimateFolderSizeFromStudyXml(StudyStorageLocation location)
		{
			float folderSize = 0.0f;
			string studyFolder = location.GetStudyPath();

			string file = Path.Combine(studyFolder, location.StudyInstanceUid + ".xml");
			if (File.Exists(file))
			{
				FileInfo finfo = new FileInfo(file);
				folderSize += finfo.Length;
			}
			file = Path.Combine(studyFolder, location.StudyInstanceUid + ".xml.gz");
			if (File.Exists(file))
			{
				FileInfo finfo = new FileInfo(file);
				folderSize += finfo.Length;
			}

			StudyXml study = LoadStudyXml(location);
			foreach (SeriesXml series in study)
			{
				string seriesFolder = Path.Combine(studyFolder, series.SeriesInstanceUid);

				foreach (InstanceXml instance in series)
				{
					if (instance.FileSize != 0)
					{
						folderSize += instance.FileSize;
					}
					else
					{
						file = Path.Combine(seriesFolder, String.Format("{0}.dcm", instance.SopInstanceUid));
						if (File.Exists(file))
						{
							FileInfo finfo = new FileInfo(file);
							folderSize += finfo.Length;
						}
					}
				}
			}

			return folderSize;
		}
开发者ID:UIKit0,项目名称:ClearCanvas,代码行数:55,代码来源:BaseServiceLockItemProcessor.cs

示例9: DoStudyLevelValidation

        private void DoStudyLevelValidation(StudyStorageLocation storageLocation, StudyXml studyXml, Study study, ServerPartition partition)
        {
            int xmlNumInstances = studyXml.NumberOfStudyRelatedInstances;
            int xmlNumSeries = studyXml.NumberOfStudyRelatedSeries;

            if (study.NumberOfStudyRelatedInstances != xmlNumInstances)
            {
                throw new StudyIntegrityValidationFailure(
                    ValidationErrors.InconsistentObjectCount,
                    new ValidationStudyInfo(study, partition),
                    String.Format("Number of study related instances in the database ({0}) does not match number of images in the filesystem ({1})",
                                  study.NumberOfStudyRelatedInstances, xmlNumInstances));
            }

            if (study.NumberOfStudyRelatedSeries != xmlNumSeries)
            {
                throw new StudyIntegrityValidationFailure(ValidationErrors.InconsistentObjectCount,
                                                          new ValidationStudyInfo(study, partition),
                                                          String.Format("Number of study related series in the database ({0}) does not match number of series in the xml ({1})",
                                                                        study.NumberOfStudyRelatedSeries, xmlNumSeries));

            }


            long dirFileCount = DirectoryUtility.Count(storageLocation.GetStudyPath(),
                                                       "*" + ServerPlatform.DicomFileExtension, true, null);

            if (xmlNumInstances != dirFileCount)
            {
                throw new StudyIntegrityValidationFailure(ValidationErrors.InconsistentObjectCount,
                                                          new ValidationStudyInfo(study, partition),
                                                          String.Format("Number of instance in xml ({0}) does not match number of images in the filesystem ({1})",
                                                                        xmlNumInstances, dirFileCount));
            }
        }
开发者ID:fparisotto,项目名称:ClearCanvas-Contrib,代码行数:35,代码来源:StudyStorageValidator.cs

示例10: GetDuplicateUidPath

        /// <summary>
        /// Helper method to return the path to the duplicate image (in the Reconcile folder)
        /// </summary>
        /// <param name="studyStorage"></param>
        /// <param name="sop"></param>
        /// <returns></returns>
        public static String GetDuplicateUidPath(StudyStorageLocation studyStorage, WorkQueueUid sop)
        {
            string dupPath = GetDuplicateGroupPath(studyStorage, sop);
            dupPath = string.IsNullOrEmpty(sop.RelativePath)
                        ? Path.Combine(dupPath,
                                       Path.Combine(studyStorage.StudyInstanceUid, sop.SopInstanceUid + "." + sop.Extension))
                        : Path.Combine(dupPath, sop.RelativePath);

            #region BACKWARD_COMPATIBILTY_CODE

            if (string.IsNullOrEmpty(sop.RelativePath) && !File.Exists(dupPath))
            {
                string basePath = Path.Combine(studyStorage.GetStudyPath(), sop.SeriesInstanceUid);
                basePath = Path.Combine(basePath, sop.SopInstanceUid);
                if (sop.Extension != null)
                    dupPath = basePath + "." + sop.Extension;
                else
                    dupPath = basePath + ".dcm";
            }

            #endregion

            return dupPath;
        }
开发者ID:m-berkani,项目名称:ClearCanvas,代码行数:30,代码来源:ServerHelper.cs

示例11: Run

		/// <summary>
		/// Do the restore.
		/// </summary>
		/// <param name="queueItem">The queue item to restore.</param>
		public void Run(RestoreQueue queueItem)
		{
            using (var context = new RestoreProcessorContext(queueItem))
            {
                try
                {
                    // Load up related classes.
                    using (IReadContext readContext = _hsmArchive.PersistentStore.OpenReadContext())
                    {
                        _archiveStudyStorage = ArchiveStudyStorage.Load(readContext, queueItem.ArchiveStudyStorageKey);
                        _serverSyntax = ServerTransferSyntax.Load(readContext, _archiveStudyStorage.ServerTransferSyntaxKey);
                        _syntax = TransferSyntax.GetTransferSyntax(_serverSyntax.Uid);

                        var parms = new StudyStorageLocationQueryParameters
                                                                    	{StudyStorageKey = queueItem.StudyStorageKey};
                    	var broker = readContext.GetBroker<IQueryStudyStorageLocation>();
                        _location = broker.FindOne(parms);
                        if (_location == null)
                        {
                            _studyStorage = StudyStorage.Load(readContext, queueItem.StudyStorageKey);
							if (_studyStorage==null)
							{
								DateTime scheduleTime = Platform.Time.AddMinutes(5);
								Platform.Log(LogLevel.Error, "Unable to find storage location, rescheduling restore request to {0}",
											 scheduleTime);
								queueItem.FailureDescription = "Unable to find storage location, rescheduling request.";
								_hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Pending, scheduleTime);
								return;
							}
                        }
                    }

                    if (_location == null)
                    {
                        Platform.Log(LogLevel.Info, "Starting restore of nearline study: {0}",
                                     _studyStorage.StudyInstanceUid);

                        // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                        // Also store the "StudyFolder" for use below
                        string studyFolder;
                        string zipFile = GetZipFileName(out studyFolder);

                        // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                        // fails, we just set back to pending and recheck.
                        if (!CanReadZip(zipFile, queueItem))
                            return;

                        RestoreNearlineStudy(queueItem, zipFile, studyFolder);
                    }
                    else
                    {
                        Platform.Log(LogLevel.Info, "Starting restore of online study: {0}", _location.StudyInstanceUid);

                         // Get the zip file path from the xml data in the ArchiveStudyStorage entry
                         // Also store the "StudyFolder" for use below
                         string studyFolder;
                         string zipFile = GetZipFileName(out studyFolder);

                         // Do a test read of the zip file.  If it succeeds, the file is available, if it 
                         // fails, we just set back to pending and recheck.
                         if (!CanReadZip(zipFile, queueItem))
                             return;

                        RestoreOnlineStudy(queueItem, zipFile, _location.GetStudyPath());
                    }       
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception processing restore request for {0} on archive {1}",
                        _studyStorage == null ? (_location == null ? string.Empty : _location.StudyInstanceUid) : _studyStorage.StudyInstanceUid,
                        _hsmArchive.PartitionArchive.Description);
                    queueItem.FailureDescription = e.Message;
                    _hsmArchive.UpdateRestoreQueue(queueItem, RestoreQueueStatusEnum.Failed, Platform.Time);
                }
            }
			
		}
开发者ID:jfphilbin,项目名称:ClearCanvas,代码行数:81,代码来源:HsmStudyRestore.cs

示例12: LoadStudyXml

		/// <summary>
		/// Load a <see cref="StudyXml"/> file for a given <see cref="StudyStorageLocation"/>
		/// </summary>
		/// <param name="location">The location a study is stored.</param>
		/// <returns>The <see cref="StudyXml"/> instance for <paramref name="location"/></returns>
		protected virtual StudyXml LoadStudyXml(StudyStorageLocation location)
		{
			StudyXml theXml = new StudyXml();

			String streamFile = Path.Combine(location.GetStudyPath(), location.StudyInstanceUid + ".xml");
			if (File.Exists(streamFile))
			{
				using (Stream fileStream = FileStreamOpener.OpenForRead(streamFile, FileMode.Open))
				{
					var theMemento = new StudyXmlMemento();

					StudyXmlIo.Read(theMemento, fileStream);

					theXml.SetMemento(theMemento);

					fileStream.Close();
				}
			}

			return theXml;
		}
开发者ID:m-berkani,项目名称:ClearCanvas,代码行数:26,代码来源:BaseServiceLockItemProcessor.cs


注:本文中的StudyStorageLocation.GetStudyPath方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。