/// <summary>
        /// Produces the asset for a single shared asset. All applicablility checks have already been completed.
        /// </summary>
        private void ProduceContentAsset(NuGetPackageObject package, JProperty sharedAsset, IReadOnlyDictionary <string, string> preprocessorValues, string preprocessedOutputDirectory)
        {
            string pathToFinalAsset = package.GetFullPathToFile(sharedAsset.Name);

            if (sharedAsset.Value["ppOutputPath"] != null)
            {
                if (preprocessedOutputDirectory == null)
                {
                    throw new ExceptionFromResource(nameof(Strings.PreprocessedDirectoryNotSet), nameof(ContentPreprocessorOutputDirectory));
                }

                // We need the preprocessed output, so let's run the preprocessor here
                pathToFinalAsset = Path.Combine(preprocessedOutputDirectory, package.Id, package.Version, (string)sharedAsset.Value["ppOutputPath"]);

                if (!File.Exists(pathToFinalAsset))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(pathToFinalAsset));

                    using (var input = new StreamReader(package.GetFullPathToFile(sharedAsset.Name), detectEncodingFromByteOrderMarks: true))
                        using (var output = new StreamWriter(pathToFinalAsset, append: false, encoding: input.CurrentEncoding))
                        {
                            Preprocessor.Preprocess(input, output, preprocessorValues);
                        }

                    _fileWrites.Add(new TaskItem(pathToFinalAsset));
                }
            }

            if ((bool)sharedAsset.Value["copyToOutput"])
            {
                string outputPath = (string)sharedAsset.Value["outputPath"] ?? (string)sharedAsset.Value["ppOutputPath"];

                if (outputPath != null)
                {
                    var item = CreateItem(package, pathToFinalAsset, targetPath: outputPath);
                    _copyLocalItems.Add(item);
                }
            }

            string buildAction = (string)sharedAsset.Value["buildAction"];

            if (!string.Equals(buildAction, "none", StringComparison.OrdinalIgnoreCase))
            {
                var item = CreateItem(package, pathToFinalAsset);

                // We'll put additional metadata on the item so we can convert it back to the real item group in our targets
                item.SetMetadata("NuGetItemType", buildAction);

                // If this is XAML, the build targets expect Link metadata to construct the relative path
                if (string.Equals(buildAction, "Page", StringComparison.OrdinalIgnoreCase))
                {
                    item.SetMetadata("Link", Path.Combine("NuGet", package.Id, package.Version, Path.GetFileName(sharedAsset.Name)));
                }

                _contentItems.Add(item);
            }
        }
        private IEnumerable <ITaskItem> CreateItems(NuGetPackageObject package, string key, bool includePdbs = true)
        {
            var values = package.TargetObject[key] as JObject;
            var items  = new List <ITaskItem>();

            if (values == null)
            {
                return(items);
            }

            foreach (var file in values.Properties())
            {
                if (Path.GetFileName(file.Name) == "_._")
                {
                    continue;
                }

                string targetPath = null;
                string culture    = file.Value["locale"]?.ToString();

                if (culture != null)
                {
                    targetPath = Path.Combine(culture, Path.GetFileName(file.Name));
                }

                var item = CreateItem(package, package.GetFullPathToFile(file.Name), targetPath);

                item.SetMetadata("Private", "false");
                item.SetMetadata(NuGetIsFrameworkReference, "false");
                item.SetMetadata(NuGetSourceType, NuGetSourceType_Package);

                string aliases = file.Value["aliases"]?.ToString();
                if (aliases != null)
                {
                    item.SetMetadata(Aliases, aliases);
                }
                items.Add(item);

                // If there's a PDB alongside the implementation, we should copy that as well
                if (includePdbs)
                {
                    var pdbFileName = Path.ChangeExtension(item.ItemSpec, ".pdb");

                    if (_fileExists(pdbFileName))
                    {
                        var pdbItem = new TaskItem(pdbFileName);

                        // CopyMetadataTo also includes an OriginalItemSpec that will point to our original item, as we want
                        item.CopyMetadataTo(pdbItem);

                        items.Add(pdbItem);
                    }
                }
            }

            return(items);
        }
        private static ITaskItem CreateItem(NuGetPackageObject package, string itemSpec, string targetPath = null)
        {
            var item = new TaskItem(itemSpec);

            item.SetMetadata(NuGetPackageIdMetadata, package.Id);
            item.SetMetadata(NuGetPackageVersionMetadata, package.Version);

            if (targetPath != null)
            {
                item.SetMetadata("TargetPath", targetPath);

                var destinationSubDirectory = Path.GetDirectoryName(targetPath);

                if (!string.IsNullOrEmpty(destinationSubDirectory))
                {
                    item.SetMetadata("DestinationSubDirectory", destinationSubDirectory + "\\");
                }
            }

            return(item);
        }