/// <summary>
        /// Gets a value indicating whether anything is different between this cache and the specified cache.
        /// </summary>
        /// <param name="other">The cache to compare against this cache.</param>
        /// <returns><see langword="true"/> if this cache is different from the specified cache; otherwise, <see langword="false"/>.</returns>
        public Boolean IsDifferentFrom(CompilerCache other)
        {
            Contract.Require(other, nameof(other));

            if (!String.Equals(versionUltraviolet, other.versionUltraviolet, StringComparison.Ordinal) ||
                !String.Equals(versionMscorlib, other.versionMscorlib, StringComparison.Ordinal))
            {
                return(true);
            }

            var keys = Enumerable.Union(this.hashes.Keys, other.hashes.Keys).ToList();

            foreach (var key in keys)
            {
                if (!this.hashes.TryGetValue(key, out var hash1))
                {
                    return(true);
                }

                if (!other.hashes.TryGetValue(key, out var hash2))
                {
                    return(true);
                }

                if (!String.Equals(hash1, hash2, StringComparison.Ordinal))
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Creates a new instance of <see cref="CompilerCache"/> by loading the contents of the specified file.
        /// </summary>
        /// <param name="path">The path to the file to load.</param>
        /// <returns>The <see cref="CompilerCache"/> instance that was created.</returns>
        public static CompilerCache FromFile(String path)
        {
            Contract.RequireNotEmpty(path, nameof(path));

            var cache = new CompilerCache();

            var lines              = File.ReadAllLines(path);
            var compilerType       = default(String);
            var versionUltraviolet = default(String);
            var versionMscorlib    = default(String);

            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];

                if (String.IsNullOrEmpty(line))
                {
                    continue;
                }

                if (i == 0 && line.StartsWith("#compiler "))
                {
                    compilerType = line.Substring("#compiler ".Length).Trim();
                    continue;
                }

                if (versionUltraviolet == default(String))
                {
                    versionUltraviolet = line;
                    continue;
                }

                if (versionMscorlib == default(String))
                {
                    versionMscorlib = line;
                    continue;
                }

                var components = line.Split((Char[])null, StringSplitOptions.RemoveEmptyEntries);
                if (components.Length != 2)
                {
                    throw new InvalidDataException();
                }

                var name = components[0];
                var hash = components[1];

                cache.hashes[name] = hash;
            }

            cache.compilerType       = compilerType;
            cache.versionUltraviolet = versionUltraviolet;
            cache.versionMscorlib    = versionMscorlib;
            return(cache);
        }
Exemple #3
0
        /// <inheritdoc/>
        public BindingExpressionCompilationResult Compile(UltravioletContext uv, BindingExpressionCompilerOptions options)
        {
            Contract.Require(uv, nameof(uv));
            Contract.Require(options, nameof(options));

            if (String.IsNullOrEmpty(options.Input) || String.IsNullOrEmpty(options.Output))
            {
                throw new ArgumentException(PresentationStrings.InvalidCompilerOptions);
            }

            var compiler = CreateCodeProvider();
            var state    = new LegacyExpressionCompilerState(uv, compiler)
            {
                GenerateInMemory         = options.GenerateInMemory,
                WorkInTemporaryDirectory = options.WorkInTemporaryDirectory,
                WriteErrorsToFile        = options.WriteErrorsToFile
            };
            var dataSourceWrapperInfos = DataSourceLoader.GetDataSourceWrapperInfos(state, options.Input);

            var cacheFile = Path.ChangeExtension(options.Output, "cache");
            var cacheNew  = CompilerCache.FromDataSourceWrappers(this, dataSourceWrapperInfos);

            if (File.Exists(options.Output))
            {
                var cacheOld = CompilerCache.TryFromFile(cacheFile);
                if (cacheOld != null && !options.IgnoreCache && !cacheOld.IsDifferentFrom(cacheNew))
                {
                    return(BindingExpressionCompilationResult.CreateSucceeded());
                }
            }

            var result = CompileViewModels(state, dataSourceWrapperInfos, options.Output, options.GenerateDebugAssembly);

            if (result.Succeeded)
            {
                if (!options.GenerateInMemory)
                {
                    cacheNew.Save(cacheFile);
                }

                if (!options.WriteCompiledFilesToWorkingDirectory && !options.WorkInTemporaryDirectory)
                {
                    state.DeleteWorkingDirectory();
                }
            }

            if (options.WriteCompiledFilesToWorkingDirectory && !options.WorkInTemporaryDirectory)
            {
                WriteCompiledFilesToWorkingDirectory(state, dataSourceWrapperInfos);
            }

            return(result);
        }
        /// <summary>
        /// Creates a new instance of <see cref="CompilerCache"/> from the specified collection of data source wrappers.
        /// </summary>
        /// <param name="compiler">The compiler which is creating this cache.</param>
        /// <param name="dataSourceWrappers">A collection of data source wrappers from which to create a cache object.</param>
        /// <returns>The <see cref="CompilerCache"/> instance that was created.</returns>
        public static CompilerCache FromDataSourceWrappers(IBindingExpressionCompiler compiler, IEnumerable <DataSourceWrapperInfo> dataSourceWrappers)
        {
            Contract.Require(compiler, nameof(compiler));
            Contract.Require(dataSourceWrappers, nameof(dataSourceWrappers));

            var types = new HashSet <Type>();
            var cache = new CompilerCache();

            cache.compilerType = compiler.GetType().FullName;

            foreach (var dataSourceWrapper in dataSourceWrappers)
            {
                if (!cache.hashes.ContainsKey(dataSourceWrapper.DataSourcePath))
                {
                    var dataSourceWrapperHash = GenerateHashForXElement(dataSourceWrapper.DataSourceDefinition.Definition);
                    cache.hashes[dataSourceWrapper.DataSourcePath] = dataSourceWrapperHash;
                }

                AddTypeReferences(dataSourceWrapper.DataSourceType, types);

                if (dataSourceWrapper.DependentWrapperInfos != null)
                {
                    foreach (var dependentWrapper in dataSourceWrapper.DependentWrapperInfos)
                    {
                        AddTypeReferences(dependentWrapper.DataSourceType, types);
                    }
                }
            }

            foreach (var type in types)
            {
                var typeHash = GenerateHashForType(type);
                cache.hashes[type.FullName] = typeHash;
            }

            return(cache);
        }