Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C#脚本调用外部应用程序方法_C#_Scripting - Fatal编程技术网

从C#脚本调用外部应用程序方法

从C#脚本调用外部应用程序方法,c#,scripting,C#,Scripting,在将脚本功能集成到我的团队构建的应用程序中方面,我已经取得了很多进展,但目前我有点陷入困境 我们有我们已经编写的数据采集软件(应用程序),我们也希望有脚本功能。我在应用程序中嵌入了一个类,可以读取和编译外部编写的脚本。例如,我可以编写一个没有以任何方式链接到应用程序的.cs文件,并在运行时调用该文件,成功地执行它 为了扩展脚本的实用性,我现在需要做的是从脚本中调用应用程序中预先存在的方法。我将尝试用以下示例来描述所有这些: 这里有我的脚本文件,在应用程序运行时,我可以随时更改它 ScriptFi

在将脚本功能集成到我的团队构建的应用程序中方面,我已经取得了很多进展,但目前我有点陷入困境

我们有我们已经编写的数据采集软件(应用程序),我们也希望有脚本功能。我在应用程序中嵌入了一个类,可以读取和编译外部编写的脚本。例如,我可以编写一个没有以任何方式链接到应用程序的.cs文件,并在运行时调用该文件,成功地执行它

为了扩展脚本的实用性,我现在需要做的是从脚本中调用应用程序中预先存在的方法。我将尝试用以下示例来描述所有这些:

这里有我的脚本文件,在应用程序运行时,我可以随时更改它

ScriptFile.cs

namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            //NEED THIS: Code to call pre-existing method in application
        }
    }
}
namespace ScriptingInterface
{
    public interface IScriptType1
    {
        string RunScript(int value);
    }
}

namespace ScriptingExample
{
    public static class ScriptingEx
    {
        public static void StartScript()
        {

            string path = @"TestScript1.cs";

            // Open the file to read from.
            string readText = File.ReadAllText(path);

            Assembly compiledScript = CompileCode(readText);

            if (compiledScript != null)
            {
                RunScript(compiledScript);
            }
        }

        static Assembly CompileCode(string code)
        {
            Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();

            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false; 
            options.GenerateInMemory = true; 
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            // Compile our code
            CompilerResults result;
            result = csProvider.CompileAssemblyFromSource(options, code);

            if (result.Errors.HasErrors)
            {
                // Report back to the user that the script has errored
                Console.WriteLine("Script has errored");

                for (int i = 0; i < result.Errors.Count; i++)
                {
                    Console.WriteLine("Error {0}: {1}", i+1, result.Errors[i]);
                }
                return null;
            }

            if (result.Errors.HasWarnings)
            {
                Console.WriteLine("Script has warnings");
            }

            return result.CompiledAssembly;
        }

        static void RunScript(Assembly script)
        {
            foreach (Type type in script.GetExportedTypes())
            {
                foreach (Type iface in type.GetInterfaces())
                {
                    if (iface == typeof(ScriptingInterface.IScriptType1))
                    {
                        ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
                        if (constructor != null && constructor.IsPublic)
                        {
                            ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
                            if (scriptObject != null)
                            {
                                //Lets run our script and display its results
                                MessageBox.Show(scriptObject.RunScript(50));
                            }
                        }
                    }
                }
            }
        }

        public static void TestExternalCall1()
        {
            Console.WriteLine("Called successfully!");
        }
    }
}
namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(ScriptingInterface.IServiceProvider serviceProvider, int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            serviceProvider.Messenger.SendMessage("Test");
        }
    }
}
很抱歉,有这么大的代码块,但我想我会包括所有内容,以防出现问题。我所要做的就是使用上面的脚本调用方法TestExternalCall,同时通过这个脚本处理程序运行它

ScriptHandler.cs

namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            //NEED THIS: Code to call pre-existing method in application
        }
    }
}
namespace ScriptingInterface
{
    public interface IScriptType1
    {
        string RunScript(int value);
    }
}

namespace ScriptingExample
{
    public static class ScriptingEx
    {
        public static void StartScript()
        {

            string path = @"TestScript1.cs";

            // Open the file to read from.
            string readText = File.ReadAllText(path);

            Assembly compiledScript = CompileCode(readText);

            if (compiledScript != null)
            {
                RunScript(compiledScript);
            }
        }

        static Assembly CompileCode(string code)
        {
            Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();

            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false; 
            options.GenerateInMemory = true; 
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            // Compile our code
            CompilerResults result;
            result = csProvider.CompileAssemblyFromSource(options, code);

            if (result.Errors.HasErrors)
            {
                // Report back to the user that the script has errored
                Console.WriteLine("Script has errored");

                for (int i = 0; i < result.Errors.Count; i++)
                {
                    Console.WriteLine("Error {0}: {1}", i+1, result.Errors[i]);
                }
                return null;
            }

            if (result.Errors.HasWarnings)
            {
                Console.WriteLine("Script has warnings");
            }

            return result.CompiledAssembly;
        }

        static void RunScript(Assembly script)
        {
            foreach (Type type in script.GetExportedTypes())
            {
                foreach (Type iface in type.GetInterfaces())
                {
                    if (iface == typeof(ScriptingInterface.IScriptType1))
                    {
                        ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
                        if (constructor != null && constructor.IsPublic)
                        {
                            ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
                            if (scriptObject != null)
                            {
                                //Lets run our script and display its results
                                MessageBox.Show(scriptObject.RunScript(50));
                            }
                        }
                    }
                }
            }
        }

        public static void TestExternalCall1()
        {
            Console.WriteLine("Called successfully!");
        }
    }
}
namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(ScriptingInterface.IServiceProvider serviceProvider, int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            serviceProvider.Messenger.SendMessage("Test");
        }
    }
}
命名空间脚本接口
{
公共接口IScriptType1
{
字符串RunScript(int值);
}
}
命名空间脚本示例
{
公共静态类ScriptingEx
{
公共静态无效StartScript()
{
字符串路径=@“TestScript1.cs”;
//打开要从中读取的文件。
字符串readText=File.ReadAllText(路径);
汇编compiledScript=CompileCode(readText);
if(compiledScript!=null)
{
RunScript(compiledScript);
}
}
静态程序集编译代码(字符串代码)
{
Microsoft.CSharp.CSharpCodeProvider csProvider=新的Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters选项=新的CompilerParameters();
options.GenerateExecutable=false;
options.GenerateInMemory=true;
options.referencedAssembly.Add(Assembly.getExecutionGassembly().Location);
//编译我们的代码
编译结果;
结果=csProvider.CompileAsemblyFromSource(选项、代码);
if(result.Errors.HasErrors)
{
//向用户报告脚本出错
Console.WriteLine(“脚本出错”);
对于(int i=0;i

如果您有任何问题,请告诉我,希望我已经说清楚了。

在我的一个项目中,我实现了类似的功能。我们通过提供
RunScript
方法的接口来解决这个问题,该方法公开了runner的不同服务。 它允许脚本编写者在提交给executor之前模拟服务并测试它们的代码。 这种方法的另一个好处是,您将在编译过程中发现不兼容问题。 作为替代解决方案,您可以使用反射,但它不是强类型和 如果您的执行者的服务已更改,您可能会在运行时遇到问题

例如:

您的宏

namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            //NEED THIS: Code to call pre-existing method in application
        }
    }
}
namespace ScriptingInterface
{
    public interface IScriptType1
    {
        string RunScript(int value);
    }
}

namespace ScriptingExample
{
    public static class ScriptingEx
    {
        public static void StartScript()
        {

            string path = @"TestScript1.cs";

            // Open the file to read from.
            string readText = File.ReadAllText(path);

            Assembly compiledScript = CompileCode(readText);

            if (compiledScript != null)
            {
                RunScript(compiledScript);
            }
        }

        static Assembly CompileCode(string code)
        {
            Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();

            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false; 
            options.GenerateInMemory = true; 
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            // Compile our code
            CompilerResults result;
            result = csProvider.CompileAssemblyFromSource(options, code);

            if (result.Errors.HasErrors)
            {
                // Report back to the user that the script has errored
                Console.WriteLine("Script has errored");

                for (int i = 0; i < result.Errors.Count; i++)
                {
                    Console.WriteLine("Error {0}: {1}", i+1, result.Errors[i]);
                }
                return null;
            }

            if (result.Errors.HasWarnings)
            {
                Console.WriteLine("Script has warnings");
            }

            return result.CompiledAssembly;
        }

        static void RunScript(Assembly script)
        {
            foreach (Type type in script.GetExportedTypes())
            {
                foreach (Type iface in type.GetInterfaces())
                {
                    if (iface == typeof(ScriptingInterface.IScriptType1))
                    {
                        ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
                        if (constructor != null && constructor.IsPublic)
                        {
                            ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
                            if (scriptObject != null)
                            {
                                //Lets run our script and display its results
                                MessageBox.Show(scriptObject.RunScript(50));
                            }
                        }
                    }
                }
            }
        }

        public static void TestExternalCall1()
        {
            Console.WriteLine("Called successfully!");
        }
    }
}
namespace SimpleScripts
{   
    public class MyScriptMul5 : ScriptingInterface.IScriptType1
    {
        public string RunScript(ScriptingInterface.IServiceProvider serviceProvider, int value)
        {
            System.Console.WriteLine("Hello World! This works!");

            serviceProvider.Messenger.SendMessage("Test");
        }
    }
}
包含宏引擎API的程序集(ScriptingInterface.dll)

宏编译器\executor

namespace ScriptingExample
{
    public static class ScriptingEx
    {
        public static void StartScript(ScriptingInterface.IServiceProvider serviceProvider)
        {
            string path = @"TestScript1.cs";

            // Open the file to read from.
            string readText = File.ReadAllText(path);

            Assembly compiledScript = CompileCode(readText);

            if (compiledScript != null)
            {
                RunScript(serviceProvider, compiledScript);
            }
        }

        static Assembly CompileCode(string code)
        {
            Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();

            CompilerParameters options = new CompilerParameters();
            options.GenerateExecutable = false; 
            options.GenerateInMemory = true; 


                options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            //Add references to ScriptingInterface.dll
            String pathToScriptingInterfaceDll = Path.Combine(Environment.CurrentDirectory, "ScriptingInterface.dll");
            options.ReferencedAssemblies.Add(pathToScriptingInterfaceDll);

            // Compile our code
            CompilerResults result;
            result = csProvider.CompileAssemblyFromSource(options, code);

            if (result.Errors.HasErrors)
            {
                // Report back to the user that the script has errored
                Console.WriteLine("Script has errored");

                for (int i = 0; i < result.Errors.Count; i++)
                {
                    Console.WriteLine("Error {0}: {1}", i+1, result.Errors[i]);
                }
                return null;
            }

            if (result.Errors.HasWarnings)
            {
                Console.WriteLine("Script has warnings");
            }

            return result.CompiledAssembly;
        }

        static void RunScript(ScriptingInterface.IServiceProvider serviceProvider, Assembly script)
        {
            foreach (Type type in script.GetExportedTypes())
            {
                foreach (Type iface in type.GetInterfaces())
                {
                    if (iface == typeof(ScriptingInterface.IScriptType1))
                    {
                        ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
                        if (constructor != null && constructor.IsPublic)
                        {
                            ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
                            if (scriptObject != null)
                            {

                                //Lets run our script and display its results
                                MessageBox.Show(scriptObject.RunScript(50));
                            }
                        }
                    }
                }
            }
        }

        public static void TestExternalCall1()
        {
            Console.WriteLine("Called successfully!");
        }
    }
}
名称空间脚本示例
{
公共静态类ScriptingEx
{
公共静态无效StartScript(ScriptingInterface.IServiceProvider服务提供程序)
{
字符串路径=@“TestScript1.cs”;
//打开要从中读取的文件。
字符串readText=File.ReadAllText(路径);
汇编compiledScript=CompileCode(readText);
if(compiledScript!=null)
{
运行脚本(serviceProvider,compiledScript);
}
}
静态程序集编译代码(字符串代码)
{
Microsoft.CSharp.CSharpCodeProvider csProvider=新的Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters选项=新的CompilerParameters();
options.GenerateExecutable=false;
options.GenerateInMemory=true;
options.referencedAssembly.Add(Assembly.getExecutionGassembly().Location);
//添加对ScriptingInterface.dll的引用
字符串pathToScriptingInterfaceDll=Path.Combine(Environment.CurrentDirectory,“ScriptingInterface.dll”);
op