最近在研究C#的动态实现,想通过CSharpCodeProvider编译新生成的文档,但是总有一个问题:如果新生成的文档需要用到很多其他类文件,那就无法获得其他类文件中的内容(我总不能把所有类文件都合到一个文件下编译吧?)请问这个问题应该如何解决呢?另外,想了解一下,在类文件中写成:
System.Windows.Forms.MessageBox.Show("Class1");
这样的,编译器是如何得知需要加载"System.Windows.Forms.dll"的呢?

解决方案 »

  1.   

    我做过类似的问题,利用反射,动态加载你的dll或exe,只要知道你的dll文件的名字,以及路径.那么就可以自动生成了.给你个例子看看吧!
    1using System;
     2
     3namespace Webtest
     4{
     5 /**//// <summary>
     6 /// ReflectTest 的摘要说明。
     7 /// </summary>
     8 public class ReflectTest
     9 {
    10  public ReflectTest()
    11  {}
    12
    13  public string WriteString(string s)
    14  {
    15   return "欢迎您," + s;
    16  }
    17
    18  /**//// <summary>
    19  /// dsajkjflasjdfalksdjfaskfd
    20  /// </summary>
    21  /// <param name="s"></param>
    22  /// <returns></returns>
    23  public static string WriteName(string s)
    24  {
    25   return "欢迎您光临," + s;
    26  }
    27
    28  public string WriteNoPara()
    29  {
    30   return "您使用的是无参数方法";
    31  }
    32 }
    33}public void test1()
     2  {
     3   System.Reflection.Assembly ass;
     4   Type type ;
     5   object obj;
     6   try
     7   {
     8    ass = System.Reflection.Assembly.LoadFile(@"d:\TestReflect.dll");
     9    type = ass.GetType("Webtest.ReflectTest");//必须使用名称空间+类名称
    10    System.Reflection.MethodInfo method = type.GetMethod("WriteString");//方法的名称
    11    obj = ass.CreateInstance("Webtest.ReflectTest");//必须使用名称空间+类名称
    12    string s = (string)method.Invoke(obj,new string[]{"jianglijun"}); //实例方法的调用
    13   
    14    Response.Write(s+"<br>");
    15    method = type.GetMethod("WriteName");//方法的名称
    16    s = (string)method.Invoke(null,new string[]{"jianglijun"}); //静态方法的调用
    17    Response.Write(s+"<br>");
    18
    19    method = type.GetMethod("WriteNoPara");//无参数的实例方法
    20    s = (string)method.Invoke(obj,null);
    21    Response.Write(s+"<br>");
    22    method = null;
    23   }
    24   catch(Exception ex)
    25   {
    26    Response.Write(ex+"<br>");
    27   }
    28   finally
    29   {
    30    ass = null;
    31    type = null;
    32    obj = null;
    33   }
    34  }
    按照列子仿造一个就可以实现你需要的了,其中用的一些技术你可以查看msdn
      

  2.   

    使用CompilerParameters来指定程序里要引用的类库文件,比如:CompilerParameters cp = new CompilerParameters();
    cp.ReferencedAssemblies.Add(“System.Dll”);
    cp.ReferencedAssemblies.Add(“System.Drawing.Dll”);CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerResults cr = provider.CompileAssemblyFromSource(cp, ...);
      

  3.   

     string   DllPath   =   Application.StartupPath   +   @"\someDLL.dll";   
      System.Reflection.Assembly   assmble   =   System.Reflection.Assembly.LoadFile(DllPath);   
        
      Type   tmpType   =   assmble.GetType("someDLL.ClassA");   
      System.Reflection.MethodInfo   tmpM   =   tmpType.GetMethod("Add");   
      object   tmpobj   =   assmble.CreateInstance("someDLL.ClassA");   
      int   i   =   (int)tmpM.Invoke(tmpobj,   new   object[]{2,3});   
        
      ----------ClassA的定义--------------------   
      using   System;   
        
      namespace   someDLL   
      {   
      ///   <summary>   
      ///   ClassA   的摘要说明。   
      ///   </summary>   
      public   class   ClassA   
      {   
      public   ClassA()   
      {   
      //   
      //   TODO:   在此处添加构造函数逻辑   
      //   
      }   
        
      public   int   Add(int   a,   int   b)   
      {   
      return   a+b;   
      }   
      }   
      }   
        
      

  4.   

    先回4楼的,因为命名空间的引用是在另外一个文件中的,而执行编译的这个类中是不知道另外那个文件使用了什么命名空间的,所以在CompilerParameters中导入前要先找到另外那个文件中到底引用了那些空间
      

  5.   

    或者你在google直接收缩"反射原理",很多例子
      

  6.   

    这称之为LINK去看编译原理就知道了你要是用过FORTRAN77,手动编译过程序就知道是怎么回事了
      

  7.   

    cp.OutputAssembly = Path.GetFileNameWithoutExtension(Name) + ".exe";
                cp.ReferencedAssemblies.Add("System.dll");
                cp.ReferencedAssemblies.Add("System.Data.dll");
                cp.ReferencedAssemblies.Add("System.Drawing.dll");
                cp.ReferencedAssemblies.Add("System.Design.dll");
                cp.ReferencedAssemblies.Add("System.Drawing.Design.dll");
                cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
                cp.ReferencedAssemblies.Add("System.Xml.dll");
                cp.ReferencedAssemblies.Add(CurrentPath + "\\ResXMaster.dll");
                cp.GenerateInMemory = false;
                CompilerResults cr = comp.CompileAssemblyFromFile(cp, new string[] { CurrentPath + "\\Program.cs", CurrentPath + "\\" + ((Control)wObject).Name + ".cs", CurrentPath + "\\" + ((Control)wObject).Name + "Designer.cs" });            if (cr.Errors.HasErrors)
                {
                    StringBuilder s = new StringBuilder();
                    foreach (CompilerError var in cr.Errors)
                    {
                        s.AppendLine(var.ToString());
                    }
                    MessageBox.Show(s.ToString());
                    return;
                }