// 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 Cookbookology.Domain.Cookbook Read(Stream inputStream)
        {
            if (inputStream == null) throw new ArgumentNullException("inputStream");

            var cookbook = new Cookbookology.Domain.Cookbook();

            using (var zip = new ZipFile(inputStream))
            {
                var decompressed = zip.GetInputStream(0); // Only one file in a MCB zip.

                var s = new XmlSerializer(typeof(Cookbook));
                var mcb = (Cookbook) s.Deserialize(decompressed);

                var converter = new MyCookbookConverter();
                cookbook = converter.ConvertToCommon(mcb);
            }

            return cookbook;
        }
        public void RoundTripConversionTestCommonToMcb()
        {
            // arrange
            var cookbook = new Cookbookology.Domain.Cookbook { Version = "4" };

            cookbook.Recipes.Add
            (
                new Cookbookology.Domain.Recipe
                {
                    AdditionalComments = "These taste great on a cold morning!",
                    Categories = new List<string> { "Breakfast", "French" },
                    CookingTime = "20 min",
                    ImagePath = @"/mnt/sdcard/MyCookBook/images/crepes.png",
                    Ingredients = new List<string> { "1 1/2 c. flour", "2 c. milk", "2 eggs", "1 1/2 tbsp. oil", "1 tbsp. sugar", "Little salt melted" },
                    Instructions = @"Pour the milk into the flour. Stir.
            Add the oil, the beaten eggs and the sugar. Stir again.
            Let the batter rest for 2 hours. The batter must be fluid. If not, add a little more milk.

            Take a frying pan, oil it and pour a small amount of batter and spread it on the bottom. Cook it on one side, then the other.
            The ""French Crepes"" must be very thin.
            You can put butter or sugar or jelly or melted chocolate on them.",
                    PreparationTime = "10 min",
                    Servings = "10 crepes",
                    SourceUri = "http://test.com",
                    Title = "Crepes",
                }
            );

            // act
            var converter = new MyCookbookConverter();
            var mcb = converter.ConvertFromCommon(cookbook);
            var resultCookbook = converter.ConvertToCommon(mcb);

            // assert
            CookbookAssert.AreEqual(cookbook, resultCookbook);
        }
        public void RoundTripConversionTestMcbToCommon()
        {
            // arrange
            var mcb = new Cookbookology.Formats.MyCookbook.Cookbook { Version = 4 };

            mcb.Recipes.Add
            (
                new Cookbookology.Formats.MyCookbook.Recipe
                {
                    Comments = "These taste great on a cold morning!",
                    Categories = "Breakfast,French",
                    CookTime = "20 min",
                    ImagePath = @"/mnt/sdcard/MyCookBook/images/crepes.png",
                    Ingredients = (new [] { "1 1/2 c. flour", "2 c. milk", "2 eggs", "1 1/2 tbsp. oil", "1 tbsp. sugar", "Little salt melted" }).Select(i => new Cookbookology.Formats.MyCookbook.Ingredient { NameAndAmount = i }).ToList(),
                    TextLines = new List<string>
                    {
                        @"Pour the milk into the flour. Stir.",
                        @"Add the oil, the beaten eggs and the sugar. Stir again.",
                        @"Let the batter rest for 2 hours. The batter must be fluid. If not, add a little more milk.",
                        string.Empty,
                        @"Take a frying pan, oil it and pour a small amount of batter and spread it on the bottom. Cook it on one side, then the other.",
                        @"The ""French Crepes"" must be very thin.",
                        @"You can put butter or sugar or jelly or melted chocolate on them.",
                    },
                    PrepTime = "10 min",
                    Quantity = "10 crepes",
                    SourceUri = "http://test.com",
                    Title = "Crepes",
                }
            );

            // act
            var converter = new MyCookbookConverter();
            var cookbook = converter.ConvertToCommon(mcb);
            var resultMcb = converter.ConvertFromCommon(cookbook);

            // assert
            CookbookAssert.AreEqual(mcb, resultMcb);
        }