/// <summary>
        /// Serializes the object.
        /// </summary>
        /// <param name="info">Serialization info object.</param>
        /// <param name="context">Streaming context.</param>
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }

            if (null != this.ListContinuationToken)
            {
                FileListContinuationToken fileLct = this.ListContinuationToken as FileListContinuationToken;
                if (fileLct != null)
                {
                    info.AddValue(ListContinuationTokenTypeName, TokenTypeFile, typeof(string));
                    info.AddValue(ListContinuationTokenName, fileLct, typeof(FileListContinuationToken));
                    return;
                }

                AzureBlobListContinuationToken azureBlobLct = this.ListContinuationToken as AzureBlobListContinuationToken;
                if (azureBlobLct != null)
                {
                    info.AddValue(ListContinuationTokenTypeName, TokenTypeAzureBlob, typeof(string));
                    info.AddValue(ListContinuationTokenName, azureBlobLct, typeof(AzureBlobListContinuationToken));
                    return;
                }

                AzureFileListContinuationToken azureFileLct = this.ListContinuationToken as AzureFileListContinuationToken;
                if (azureFileLct != null)
                {
                    info.AddValue(ListContinuationTokenTypeName, TokenTypeAzureFile, typeof(string));
                    info.AddValue(ListContinuationTokenName, azureFileLct, typeof(AzureFileListContinuationToken));
                    return;
                }
            }
            else
            {
                info.AddValue(ListContinuationTokenTypeName, "", typeof(string));
            }
        }
        /// <summary>
        /// Enumerates the files present in the storage location referenced by this object.
        /// </summary>
        /// <param name="cancellationToken">CancellationToken to cancel the method.</param>
        /// <returns>Enumerable list of TransferEntry objects found in the storage location referenced by this object.</returns>
        public IEnumerable <TransferEntry> EnumerateLocation(CancellationToken cancellationToken)
        {
            Utils.CheckCancellation(cancellationToken);

            string filePattern = string.IsNullOrEmpty(this.SearchPattern) ? DefaultFilePattern : this.SearchPattern;

            SearchOption searchOption = this.Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
            IEnumerable <EnumerateDirectoryHelper.LocalEnumerateItem> directoryEnumerator = null;
            ErrorEntry errorEntry = null;

            Utils.CheckCancellation(cancellationToken);

            string fullPath     = null;
            string baseFullPath = null;

            if (Interop.CrossPlatformHelpers.IsWindows)
            {
                fullPath = TransferManager.Configurations.SupportUncPath ?
                           LongPath.ToUncPath(this.location.DirectoryPath) :
                           LongPath.GetFullPath(this.location.DirectoryPath);
                baseFullPath = TransferManager.Configurations.SupportUncPath ?
                               LongPath.ToUncPath(this.baseDirectory) :
                               LongPath.GetFullPath(this.baseDirectory);
            }
            else
            {
                fullPath     = Path.GetFullPath(this.location.DirectoryPath);
                baseFullPath = Path.GetFullPath(this.baseDirectory);
            }

            fullPath     = AppendDirectorySeparator(fullPath);
            baseFullPath = AppendDirectorySeparator(baseFullPath);

            bool isBaseDirectory = string.Equals(fullPath, baseFullPath);

            try
            {
                // Directory.GetFiles/EnumerateFiles will be broken when encounted special items, such as
                // files in recycle bins or the folder "System Volume Information". Rewrite this function
                // because our listing should not be stopped by these unexpected files.
                directoryEnumerator = EnumerateDirectoryHelper.EnumerateAllEntriesInDirectory(
                    fullPath,
                    filePattern,
                    this.listContinuationToken == null ? null : this.listContinuationToken.FilePath,
                    searchOption,
                    followSymlink,
                    isBaseDirectory,
                    cancellationToken);
            }
            catch (Exception ex)
            {
                string errorMessage = string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.FailedToEnumerateDirectory,
                    this.location.DirectoryPath,
                    filePattern);

                TransferException exception =
                    new TransferException(TransferErrorCode.FailToEnumerateDirectory, errorMessage, ex);
                errorEntry = new ErrorEntry(exception);
            }

            if (null != errorEntry)
            {
                // We any exception we might get from Directory.GetFiles/
                // Directory.EnumerateFiles. Just return an error entry
                // to indicate error occured in this case.
                yield return(errorEntry);
            }

            if (null != directoryEnumerator)
            {
                foreach (var entry in directoryEnumerator)
                {
                    Utils.CheckCancellation(cancellationToken);

                    string relativePath = entry.Path;

                    if (relativePath.StartsWith(baseFullPath, StringComparison.OrdinalIgnoreCase))
                    {
                        relativePath = relativePath.Remove(0, baseFullPath.Length);
                    }

                    string continuationTokenPath = entry.Path;
                    continuationTokenPath = continuationTokenPath.Remove(0, fullPath.Length);
                    var continuationToken = new FileListContinuationToken(continuationTokenPath);

                    if (relativePath.Length > Constants.MaxRelativePathLength)
                    {
                        relativePath = relativePath.Substring(0, Constants.MaxRelativePathLength / 2) + "..." + relativePath.Substring(relativePath.Length - Constants.MaxRelativePathLength / 2);
                    }

                    if (entry.IsDirectory)
                    {
                        yield return(new DirectoryEntry(
                                         relativePath,
                                         LongPath.Combine(this.baseDirectory, relativePath),
                                         continuationToken));
                    }
                    else
                    {
                        yield return(new FileEntry(
                                         relativePath,
                                         LongPath.Combine(this.baseDirectory, relativePath),
                                         continuationToken));
                    }
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="FileEntry" /> class.
 /// </summary>
 /// <param name="relativePath">Relative path of the file indicated by this file entry.</param>
 /// <param name="fullPath">Full path of the file indicated by this file entry.</param>
 /// <param name="continuationToken">Continuation token when listing to this entry.</param>
 public FileEntry(string relativePath, string fullPath, FileListContinuationToken continuationToken)
     : base(relativePath, continuationToken)
 {
     this.FullPath = fullPath;
 }