public Cookbookology.Domain.Cookbook ConvertToCommon(Cookbookology.Formats.MyCookbook.Cookbook mcb)
        {
            var cookbook = new Cookbookology.Domain.Cookbook
            {
                Version = mcb.Version.ToString(),
            };

            foreach (var mcbRecipe in mcb.Recipes)
            {
                var recipe = new Cookbookology.Domain.Recipe()
                {
                    Categories = (mcbRecipe.Categories == null) ? new List<string>() : new List<string>(mcbRecipe.Categories.Split(new [] {','})),
                    AdditionalComments = mcbRecipe.Comments,
                    CookingTime = mcbRecipe.CookTime,
                    ImagePath = mcbRecipe.ImagePath,
                    Ingredients = (mcbRecipe.Ingredients == null) ? new List<string>() : mcbRecipe.Ingredients.Select(i =>i.NameAndAmount).ToList(),
                    PreparationTime = mcbRecipe.PrepTime,
                    Servings = mcbRecipe.Quantity,
                    SourceUri = mcbRecipe.SourceUri,
                    Instructions = string.Join("\r\n", mcbRecipe.TextLines),
                    Title = mcbRecipe.Title,
                };

                cookbook.Recipes.Add(recipe);
            }

            return cookbook;
        }
        public Cookbookology.Formats.MyCookbook.Cookbook ConvertFromCommon(Cookbookology.Domain.Cookbook cookbook)
        {
            var mcb = new Cookbookology.Formats.MyCookbook.Cookbook
            {
                Version = int.Parse(cookbook.Version),
            };

            foreach (var recipe in cookbook.Recipes)
            {
                var mcbRecipe = new Cookbookology.Formats.MyCookbook.Recipe()
                {
                    Categories = string.Join(",", recipe.Categories),
                    Comments = recipe.AdditionalComments,
                    CookTime = recipe.CookingTime,
                    ImagePath = recipe.ImagePath,
                    Ingredients = recipe.Ingredients.Select(i => new Ingredient { NameAndAmount = i }).ToList(),
                    PrepTime = recipe.PreparationTime,
                    Quantity = recipe.Servings,
                    SourceUri = recipe.SourceUri,
                    TextLines = new List<string>(recipe.Instructions.Split(new [] { "\r\n", "\r", "\n" }, StringSplitOptions.None)),
                    Title = recipe.Title,
                };

                mcb.Recipes.Add(mcbRecipe);
            }

            return mcb;
        }
        // See this link for details on zipping using SharpZipLib:  https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#wiki-anchorCreate
        public void Write(Cookbookology.Domain.Cookbook cookbook, Stream outputStream)
        {
            if (cookbook == null) throw new ArgumentNullException("cookbook");
            if (outputStream == null) throw new ArgumentNullException("outputStream");

            var converter = new MyCookbookConverter();
            var mcb = converter.ConvertFromCommon(cookbook);

            var ms = new MemoryStream();
            var s = new XmlSerializer(typeof(Cookbook));
            s.Serialize(ms, mcb);
            ms.Position = 0; // reset to the start so that we can write the stream

            // Add the cookbook as a single compressed file in a Zip
            using (var zipStream = new ZipOutputStream(outputStream))
            {
                zipStream.SetLevel(3); // compression
                zipStream.UseZip64 = UseZip64.Off; // not compatible with all utilities and OS (WinXp, WinZip8, Java, etc.)

                var entry = new ZipEntry(mcbFileName);
                entry.DateTime = DateTime.Now;

                zipStream.PutNextEntry(entry);
                StreamUtils.Copy(ms, zipStream, new byte[4096]);
                zipStream.CloseEntry();

                zipStream.IsStreamOwner = false; // Don't close the outputStream (parameter)
                zipStream.Close();
            }
        }
        public static void AreEqual(Cookbookology.Formats.MyCookbook.Cookbook expected, Cookbookology.Formats.MyCookbook.Cookbook actual)
        {
            Assert.AreEqual(expected.Version, actual.Version);
            Assert.AreEqual(expected.Recipes.Count, actual.Recipes.Count);

            for (int i = 0; i < expected.Recipes.Count; i++)
            {
                var expectedRecipe = expected.Recipes[i];
                var actualRecipe = actual.Recipes[i];

                Assert.AreEqual(expectedRecipe.Comments, actualRecipe.Comments);
                Assert.AreEqual(expectedRecipe.Categories, actualRecipe.Categories);
                Assert.AreEqual(expectedRecipe.CookTime, actualRecipe.CookTime);
                Assert.AreEqual(expectedRecipe.ImagePath, actualRecipe.ImagePath);
                EnumerableAssert.AreEqual(expectedRecipe.Ingredients.Select(x => x.NameAndAmount), actualRecipe.Ingredients.Select(x => x.NameAndAmount));
                EnumerableAssert.AreEqual(expectedRecipe.TextLines, actualRecipe.TextLines);
                Assert.AreEqual(expectedRecipe.PrepTime, actualRecipe.PrepTime);
                Assert.AreEqual(expectedRecipe.Quantity, actualRecipe.Quantity);
                Assert.AreEqual(expectedRecipe.SourceUri, actualRecipe.SourceUri);
                Assert.AreEqual(expectedRecipe.Title, actualRecipe.Title);
            }
        }
        public static void AreEqual(Cookbookology.Domain.Cookbook expected, Cookbookology.Domain.Cookbook actual)
        {
            Assert.AreEqual(expected.Version, actual.Version);
            Assert.AreEqual(expected.Recipes.Count, actual.Recipes.Count);

            for (int i = 0; i < expected.Recipes.Count; i++)
            {
                var expectedRecipe = expected.Recipes[i];
                var actualRecipe = actual.Recipes[i];

                Assert.AreEqual(expectedRecipe.AdditionalComments, actualRecipe.AdditionalComments);
                EnumerableAssert.AreEqual(expectedRecipe.Categories, actualRecipe.Categories);
                Assert.AreEqual(expectedRecipe.CookingTime, actualRecipe.CookingTime);
                Assert.AreEqual(expectedRecipe.ImagePath, actualRecipe.ImagePath);
                EnumerableAssert.AreEqual(expectedRecipe.Ingredients, actualRecipe.Ingredients);
                Assert.AreEqual(expectedRecipe.Instructions, actualRecipe.Instructions);
                Assert.AreEqual(expectedRecipe.PreparationTime, actualRecipe.PreparationTime);
                Assert.AreEqual(expectedRecipe.Servings, actualRecipe.Servings);
                Assert.AreEqual(expectedRecipe.SourceUri, actualRecipe.SourceUri);
                Assert.AreEqual(expectedRecipe.Title, actualRecipe.Title);
            }
        }