比如一个C#文件如下:
using System;
public class Script
{
    public object Run(string[] Parameters)
   {
       string s;
       s="select * from table1";
       return s;    
   }
}
然后,我在程序运行过程中,程序先编译这个文件,然后调用,实时得到它的反回值s="select * from table1";
多谢。 

解决方案 »

  1.   

    public object Run(string[] Parameters)==>
    改成靜態函數public static object Run(string[] Parameters),實時調用就可
      

  2.   

    有一个很土的办法不知道行不行:1。用Microsoft.CSharp.Compiler.Compile动态编译生成一个dll;
    2。使用Assembly.LoadFrom得到这个临时的dll;
    3。使用MethodInfo得到你想要运行的公用函数Run;
    4。用Activator.CreateInstance生成Script的实例;
    5。MethodInfo.Invoke调用这个函数;
    6。得到函数返回值。
      

  3.   

    差点忘了:
    7。枪毙那个临时生成的dll。
      

  4.   

    大家都知道,在ASP.NET中利用CodeBehind技术编写好的文件必须先通过编译,然后才能被执行。我们一般是在VS.NET中或者命令行下进行编译,那么现在的问题就是在程序中进行编译,也就是自己通过做好的规则动态生成一些程序源文件、然后对其进行编译。查看.Net Framework中提供的类库,发现了Microsoft.Csharp这个命名空间,其中有一个类Compiler。要调用这个类库必须先在引用中添加D:\WINNT\Microsoft.NET\Framework\v1.0.3705\cscompmgd.dll这个文件,这是我机器上的路径,各位根据自己机器所在路径设置吧。
    仔细研究Compiler这个类:不需要初始化,直接可使用Compile方法,其中包含了5个参数。string[] sourceTexts 源代码数组 其中每一个值包含一个文件中的源码string[] sourceTextNames 源文件名数组 其中每一个值包含了一个文件名和上面的源代码数组中的值一一对应。string target 输出的文件名 string[] imports 引用类库数组 也就是我们在VS.net中引用的那些类库的文件路径,一般都是dll文件,其中一个值表示一个引用文件。IDictionary options 参数设置,实际上这也是一个数组,可以包含多个参数,具体的参数我在下面的部分会讲到。
    实际这个Compile这个方法要求我们输入这些条件:1、源代码——这个是必须的,没有源代码没法编译,那么源代码要求我们从程序文件中读取出来。2、源文件的名称,和读取出的源代码一一对应。3、编译输出的文件名,也可不填 4、引用的类库文件,如System.dll,System.data.dll这些都是经常会用到的。5、其他参数设置
    第一步:创建一个类及调用方法首先我们创建一个Classusing System;using System.IO;using System.Text;using Microsoft.CSharp;
    namespace MyTest{private String[] filelist; //文件列表private String[] cscode; //源代码private String[] filename; //文件名private String[] import; //引用类库public class MyComplier(){
    //这里我做了一个简单的方法,要求用户输入两个参数,一个是文件夹的绝对路径另外一个是输出的文件路径public CompilerError[] MyCompile(String realpath,String output){//……………………}
    }}那么下面我们会一步步来讲解如何实现这个方法。
    第二步:读取程序文件列表
    由于使用CodeBehind,那么实际上要编译的也就是扩展名为CS的文件。首先读取文件列表,制作一个方法用来读取目录下的文件路径:通过用户输入的绝对路径对文件进行整理搜索。
    public String[] GetFileList(String realpath)//输入绝对路径{return System.IO.Directory.GetFiles(realpath,”*.cs”);//输入搜索条件}
    本方法将要编译的真实目录传递进入,然后返回目录下扩展名为CS的文件路径列表。那么读取文件的列表将会为文件中代码的获取及文件名的获取做准备。
    第三步:读取程序文件内容//这里我们调用了第二步建立的方法来获取文件列表filelist= GetFileList(realpath); //获取文件路径列表//根据文件的数量创建数组cscode=new String[filelist.Length]; //建立源代码数组String[] filename=new String[filelist.Length];//建立源文件名数组//通过循环获取每个文件的信息每增加到对应的数组中For (int I=0;I {String filepath= filelist. GetValue(i).ToString();//获取单个文件路径cscode[I]= ReadTxtFile(filepath, Encoding.GetEncoding("GB2312"));//读取源文件中的代码、这里的编码为GB2312,也可设置为其他,这里调用的是我们下面创建的一个方法filename[I]= System.IO.Path.GetFileName(filepath);//获取文件名}
    //读取文本文件内容public String ReadTxtFile(String path,Encoding encode){String str="";try{if (File.Exists(path)){ StreamReader sr=new StreamReader(path,encode);str=sr.ReadToEnd();sr.Close();}}catch(IOException ex){Console.Write(ex.ToString());}return str;}经过第二步之后我们已经满足了Compile方法所需的两个参数了,那么接下来将是对文件的输出及引用的一些配置。
    第四步:配置输出文件名及路径此处可根据你的需要,设置文件和路径,例如:E:\test\bin\test.dll String output=” E:\\test\\bin\\test.dll”;这里我们根据用户输入的路径进行操作。
    第五步:配置引用的类库文件那么只要是你在程序引用到的类库,在此处都必须加入到数组中。import=new String[10];//定义一个数组,数组长度根据你所需要引用的文件数量决定import[0]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.dll";import[1]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\IEHost.dll";import[2]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Data.dll";import[3]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Drawing.dll";import[4]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Web.dll";import[5]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Xml.dll";import[6]="D:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\cscompmgd.dll";上面的是我们经常用到的一些类库,除此之外,你自己编写的一些类库,如果也被引用到了,那么也必须增加到数组中。
    第六步:进行属性参数配置这里系统提供给了我们一个接口:Idictionary,这个接口可使用以下几个类来实现。
    ListDictionary 使用单链接列表实现 IDictionary。建议用于通常包含 10 个或 10 个以下项的集合。HybridDictionary在集合较小时,使用 ListDictionary 来实现 IDictionary,然后当集合变大时,切换到 Hashtable。还有其他一些,我感觉用不上,这里就不讲了。那么,具体来看看:
    System.Collections.IDictionary configs=new System.Collections.Specialized.ListDictionary();//实现这个接口configs.Add("target","library"); //配置输出文件类型为库文件,这个参数是必须的其中”target”为文件的格式属性,”library”为属性的值。
    其他属性有:addmodule 导入元数据 要包含在此程序集内的模块列表。模块名必须用竖线或管道字符分隔。值的类型必须是 String。baseaddress 库的基址。值的类型必须是 Uint32bugreport 产生错误报告文件。值的类型必须是 String。checked 检查整数算法 设置默认表达式计算为选中(或未选中)。值的类型必须是 Boolean。Debug发出调试信息 值的类型必须是 Boolean。不能指定“全部”或“pdbonly”。Lib 指定程序集引用位置 查找模块和引用的程序集时要搜索的附加路径。值的类型必须是 String。Unsafe启用不安全模式 允许不安全构造。值的类型必须是 Booleanwin32icon自动生成的 Win32 资源的 Win32 图标。值的类型必须是String这里讲出主要的一些参数,还有一些由于用得比较少,那么就不一一列出了。
    第七步:程序编译CompilerError[] ce= Compiler.Compile(cscode,filename, output,import, configs);那么实际上我们最后的编译也就是调用这个方法,此方法将会返回一个包含出错信息的数组。其中记录了编译过程中的出错信息,如果有错误信息返回,则编译无法通过。
    最后我们将第一步中的方法整合:
    public CompilerError[] MyCompile(String realpath,String output){//……………………通过上面的方法获取到参数,最后执行编译。CompilerError[] ce= Compiler.Compile(cscode,filename, output,import, configs);return ce;}
    到这里,基本上整个编译过程就完成了,大家可以在Aspx页面中调用或者在其他的类中调用,编译出来的效果和VS.net比起来一点不差,而且速度也非常快。大家甚至可以构建一个基于Web的简易的集成开发环境,当然这是后话了。最后大家如果编译完成后,不要忘记删除掉源文件,这个很简单,我就不多讲了。
      

  5.   

    非常感谢,我用这种方法来实现用户自定义报表,程序中传参数给用户,用户根据这个参数可以写脚本(也就是C#代码),然后编译返回一个数据源。:)
    其实cscompmgd.dll也与csc.exe命令差不多的。我看了别人的软件,应该是snowfox0318, possible_Y两位所讲的方法能实现。
    但现在有一个问题,我生成dll文件,在程序中执行如下步骤后:
    4、用Activator.CreateInstance生成Script的实例;
    5、MethodInfo.Invoke调用这个函数;
    那个dll文件就不能删除了,必须退出程序后才能删除,是不是我哪个地方没做好。
    我在下面的地方也提了这个问题
    http://community.csdn.net/Expert/topic/3989/3989603.xml?temp=.6621363