コード例 #1
0
        /// <summary>
        /// Compiles the module.
        /// </summary>
        /// <param name="codeTexts">The code texts.</param>
        /// <param name="module">The module.</param>
        /// <param name="references">The references.</param>
        /// <param name="objParams">The object parameters.</param>
        /// <param name="pluginSystemVersion">The plugin system version.</param>
        /// <returns></returns>
        static public PluginCommon CompileModule(string[] codeTexts, string module,
                                                 string[] references, object objParams, string pluginSystemVersion)
        {
            string compiledName = AssemblyUtils.CompiledPluginName(module, pluginSystemVersion,
                                                                   string.Concat("-", AssemblyUtils.TimeStampForFile(DateTime.Now), ".dll"));
            //string compiledName = CompiledPluginName(module, pluginSystemVersion,
            //        string.Concat("-", Path.GetRandomFileName().Substring(0, 8), ".dll"));
            CompilerParameters cp =
                new CompilerParameters(new[] { "System.Windows.Forms.dll", "System.dll",
                                               "System.Data.dll", "System.Drawing.dll", "System.Xml.dll" },
                                       chachePath + compiledName,
#if DEBUG
                                       true);
#else
                                       false);
#endif
            cp.TempFiles = new TempFileCollection(chachePath, false);  //set directory
            cp.ReferencedAssemblies.Add(System.Windows.Forms.Application.ExecutablePath);
            cp.GenerateExecutable = false;
            cp.GenerateInMemory   = false;
            cp.CompilerOptions    = "/optimize";
            cp.WarningLevel       = 4; //to do not consider C00618 warning (obsolete PluginBaseV0_0 class)
            cp.MainClass          = "Gear.PluginSupport." + module;
            //traverse list adding not null nor empty texts
            foreach (string s in references)
            {
                if (!string.IsNullOrEmpty(s))
                {
                    cp.ReferencedAssemblies.Add(s);
                }
            }
            CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
            try
            {
                if (!Directory.Exists(chachePath))
                {
                    Directory.CreateDirectory(chachePath);
                }
                else
                {
                    try
                    {
                        Directory.Delete(chachePath, true);
                        Directory.CreateDirectory(chachePath);
                    }
                    catch (Exception e)
                    {
                        CompilerError c =
                            new CompilerError(string.Empty, 0, 0, "Pre-build", e.Message);
                        m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                        return(null);
                    }
                }
                //write the codes to compile later
                string[] sourceFiles = new string[codeTexts.Length];
                for (int i = 0; i < codeTexts.Length; i++)
                {
                    sourceFiles[i] = string.Format(chachePath + "{0}-{1}.cs",
                                                   AssemblyUtils.CompiledPluginName(module, pluginSystemVersion,
                                                                                    string.Empty), i);
                    File.WriteAllText(sourceFiles[i], codeTexts[i]);
                }
                AppDomainSetup adSetup = new AppDomainSetup();
                adSetup.ApplicationBase = System.Environment.CurrentDirectory;
                adSetup.ApplicationName = "Plugin space App";
                adSetup.ShadowCopyFiles = "true";
                adSetup.CachePath       = chachePath;
                AppDomain pluginDomain = AppDomain.CreateDomain("pluginDomain", null, adSetup);

                //compile the assembly
                CompilerResults results = provider.CompileAssemblyFromFile(cp, sourceFiles);
                if (results.Errors.HasErrors | results.Errors.HasWarnings)
                {
                    m_Errors = results.Errors;
                    return(null);
                }
                string compiledAssembly = results.CompiledAssembly.FullName;
                //PrintAssembliesLoaded(AppDomain.CurrentDomain, results.CompiledAssembly, true);

                //byte[] rawAssembly = loadFile(@".\cache\" + compiledName);
                //Assembly assemblyPlugin = pluginDomain.Load(rawAssembly, null);
                //PrintAssembliesLoaded(pluginDomain, assemblyPlugin, true);

                // TODO ASB: see links to help about running in a different AppDomain
                //http://stackoverflow.com/questions/5380246/loading-services-from-other-dll-and-run-them-isolated/5380317#5380317
                //http://stackoverflow.com/questions/599731/use-the-serializable-attribute-or-subclassing-from-marshalbyrefobject
                //explore how to use MarshalByRefObject: http://www.softwareinteractions.com/blog/2010/2/7/loading-and-unloading-net-assemblies.html
                //http://stackoverflow.com/questions/1687245/use-appdomain-to-load-unload-external-assemblies
                object target = pluginDomain.CreateInstanceAndUnwrap(
                    compiledAssembly,                               //string assemblyName
                    module,                                         //string typeName
                    false,                                          //bool ignoreCase
                    BindingFlags.Public | BindingFlags.Instance,    //BindingFlags bindingAttr
                    null,                                           //Binder binder
                    (objParams != null) ?                           //object[] args
                    new object[] { objParams } :
                    null,
                    null,                                           //CultureInfo culture
                    null);                                          //object[] activationAttributes
                PrintAssembliesLoaded(pluginDomain, results.CompiledAssembly, false);
                if (target == null)
                {
                    CompilerError c = new CompilerError(string.Empty, 0, 0, "CS0103",
                                                        "The name '" + module + "' does not exist in the current context." +
                                                        " Does the class name is the same that is declared in c# code?");
                    m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                    return(null);
                }
                else if (!PluginSystem.InstanceOneOfValidClasses(target))
                {
                    CompilerError c = new CompilerError(string.Empty, 0, 0, "CS0029",
                                                        "Cannot implicitly convert type '" + target.GetType().FullName +
                                                        "' to '" + PluginSystem.GetPluginBaseType(pluginSystemVersion).FullName + "'");
                    m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                    return(null);
                }

                m_Errors = null;
                return((PluginCommon)target);
            }
            catch (Exception e)
            {
                CompilerError c = new CompilerError(string.Empty, 0, 0, "Runtime",
                                                    string.Format("Plugin '{0}' - {1}", module, e.Message));
                m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                return(null);
            }
        }
コード例 #2
0
        /// @brief Dynamic compiling & loading for a plugin.
        /// @details Try to dynamically compile a module for the plugin, based on supplied
        /// C# code and other C# modules referenced, using Reflexion. If the compiling fails,
        /// it gives a list of errors, intended to be showed in the plugin view.
        /// @param[in] codeTexts C# Source code based on PluginBase class, to implement the plugin.
        /// @param[in] sourceFiles Source file (with path).
        /// @param[in] module Class name of the plugin.
        /// @param[in] references String array with auxiliary references used by your plugin.
        /// See notes for defaults used.
        /// @param[in] objParams Reference to a PropellerCPU of this instance, to be passed
        /// as a parameter to the constructor of the new plugin class instance.
        /// @param[in] pluginSystemVersion Witch plugin system version to compile.
        /// @returns New Plugin class instance compiled (on success), or NULL (on fail).
        /// @note There are some references already added, so you don't need to include on your
        /// plugins:
        /// @li `using System;` @li `using System.Data;` @li `using System.Drawing;`
        /// @li `using System.Windows.Forms;` @li `using System.Xml;`
        /// @version v15.03.26 - Modified the logic.
        static public PluginCommon LoadModule(string[] codeTexts, string[] sourceFiles,
                                              string module, string[] references, object objParams, string pluginSystemVersion)
        {
            const string chachePath   = @".\plugincache\";
            string       compiledName =
                AssemblyUtils.CompiledPluginName(module, pluginSystemVersion, ".dll");
            CompilerParameters cp = new CompilerParameters(
                new[] { "System.Windows.Forms.dll", "System.dll", "System.Data.dll",
                        "System.Drawing.dll", "System.Xml.dll" },
                chachePath + compiledName,
                false);

            if (!Directory.Exists(chachePath))
            {
                Directory.CreateDirectory(chachePath);
            }
            cp.TempFiles = new TempFileCollection(chachePath, false);  //set directory
            cp.ReferencedAssemblies.Add(System.Windows.Forms.Application.ExecutablePath);
            cp.IncludeDebugInformation = false;
            cp.GenerateExecutable      = false;
            cp.GenerateInMemory        = true;
            cp.CompilerOptions         = "/optimize";
            cp.WarningLevel            = 4; //to do not consider C00618 warning (obsolete PluginBaseV0_0 class)
            cp.MainClass = "Gear.PluginSupport." + module;
            //traverse list adding not null nor empty texts
            foreach (string s in references)    //traverse list adding not null or empty texts
            {
                if (!string.IsNullOrEmpty(s))
                {
                    cp.ReferencedAssemblies.Add(s);
                }
            }

            CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();

            try
            {
                //compile source codes into a memory assembly
                CompilerResults results = provider.CompileAssemblyFromSource(cp, codeTexts);

                if (results.Errors.HasErrors | results.Errors.HasWarnings)
                {
                    m_Errors = results.Errors;
                    return(null);
                }
//#if DEBUG
//                //write the code to file to enable debug
//                for (int i = 0; i < codeTexts.Length; i++ )
//                    File.WriteAllText(
//                        codefile.Replace(".cs", string.Format(".{0}.cs",i)),
//                        codeTexts[i] );
//#endif
                PrintAssembliesLoaded(AppDomain.CurrentDomain, results.CompiledAssembly, true);
                //then instantiate plugin class
                object target = results.CompiledAssembly.CreateInstance(
                    module,                                         //string typeName
                    false,                                          //bool ignoreCase
                    BindingFlags.Public | BindingFlags.Instance,    //BindingFlags bindingAttr
                    null,                                           //Binder binder
                    (objParams != null) ?                           //object[] args
                    new object[] { objParams } :
                    null,
                    null,                                           //CultureInfo culture
                    null);                                          //object[] activationAttributes

                PrintAssembliesLoaded(AppDomain.CurrentDomain, results.CompiledAssembly, false);
                if (target == null)
                {
                    CompilerError c = new CompilerError(string.Empty, 0, 0, "CS0103",
                                                        "The name '" + module + "' does not exist in the current context." +
                                                        " Does the class name is the same that is declared in c# code?");
                    m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                    return(null);
                }
                else if (!PluginSystem.InstanceOneOfValidClasses(target))
                {
                    CompilerError c = new CompilerError(string.Empty, 0, 0, "CS0029",
                                                        "Cannot implicitly convert type '" + target.GetType().FullName +
                                                        "' to '" + PluginSystem.GetPluginBaseType(pluginSystemVersion).FullName + "'");
                    m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                    return(null);
                }

                m_Errors = null;
                return((PluginCommon)target);
            }
            catch (Exception e)
            {
                CompilerError c = new CompilerError(string.Empty, 0, 0, "Runtime",
                                                    string.Format("Plugin '{0}' - {1}", module, e.Message));
                m_Errors = new CompilerErrorCollection(new CompilerError[] { c });
                return(null);
            }
        }