2016-03-15 125 views
0

我有一个基于插件的web应用程序,它允许管理员为用户分配各种小功能(实际功能不重要)。 此功能是可配置的,并且理解插件的管理员很重要。管理员足够技术,能够阅读这些插件的非常简单的源代码。 (大部分只是算术)。在库中包含库的源代码

我知道有一个已经有大约从从源头建立了一个DLL中访问源代码的几个问题:

How to include source code in dll?例如。

我已经玩弄.cs文件到一个/ Resources文件夹。但是,使用预生成事件做这件事显然不包括项目中的这些文件。所以VS永远不会复制它们,我无法在Resources对象上访问它们。

有没有一种方法可以引用特定类的源代码...来自于我缺少的相同程序集?或者,也可以选择从该组件的pdb中提取COMPLETE源的方法?我很高兴部署详细的PDB文件。这部分解决方案没有安全风险。

由于我已经访问了源代码,我不想去反编译它来显示它。这看起来很浪费和过于复杂。

回答

0

从@ Luaan建议使用预构建步骤创建单个压缩文件夹我创建了一个基本控制台应用程序,将源文件打包到特定位置的压缩文件中。

static void Main(string[] args) 
     { 
      Console.WriteLine("Takes a folder of .cs files and flattens and compacts them into a .zip." + 
          "Arg 1 : Source Folder to be resursively searched" + 
          "Arg 2 : Destination zip file" + 
          "Arg 3 : Semicolon List of folders to ignore"); 

      if (args[0] == null || args[1] == null) 
      { 
       Console.Write("Args 1 or 2 missing"); 
       return; 
      }; 

      string SourcePath = args[0]; 
      string ZipDestination = args[1]; 

      List<String> ignoreFolders = new List<string>(); 
      if (args[2] != null) 
      { 
       ignoreFolders = args[2].Split(';').ToList(); 
      } 

      var files = DirSearch(SourcePath, "*.cs", ignoreFolders); 
      Console.WriteLine($"{files.Count} files found to zip"); 

      if (File.Exists(ZipDestination)) 
      { 
       Console.WriteLine("Destination exists. Deleting zip file first"); 
       File.Delete(ZipDestination); 
      } 

      int zippedCount = 0; 
      using (FileStream zipToOpen = new FileStream(ZipDestination, FileMode.OpenOrCreate)) 
      { 
       using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create)) 
       { 
        foreach (var filePath in files) 
        { 
         Console.WriteLine($"Writing {Path.GetFileName(filePath)} to zip {Path.GetFileName(ZipDestination)}"); 
         archive.CreateEntryFromFile(filePath, Path.GetFileName(filePath)); 
         zippedCount++; 
        } 
       } 
      } 
      Console.WriteLine($"Zipped {zippedCount} files;"); 
     } 

     static List<String> DirSearch(string sDir, string filePattern, List<String> excludeDirectories) 
     { 
      List<String> filePaths = new List<string>(); 
      foreach (string d in Directory.GetDirectories(sDir)) 
      { 
       if (excludeDirectories.Any(ed => ed.ToLower() == d.ToLower())) 
       { 
        continue; 
       } 

       foreach (string f in Directory.GetFiles(d, filePattern)) 
       { 
        filePaths.Add(f); 
       } 
       filePaths.AddRange(DirSearch(d, filePattern, excludeDirectories)); 
      } 

      return filePaths; 
     } 

需要3个参数为源目录,输出压缩文件和一个“;”要排除的路径的分隔列表。我刚把它建成二进制文件。致力于简化源代码管理,并将其纳入为我希望源代码的项目进行的预生成。

没有错误检查真的,我敢肯定它会失败的失踪参数。但如果有人想要它。这里是!再次感谢@Luaan澄清PDB并不是那么有用!

1

源代码不包含在DLL中,也不在PDB中(PDB只包含DLL中的地址与源代码中相应的代码行之间的链接,以及其他琐事像变量名称)。

预生成事件是一个可能的解决方案 - 只要确保它生成包含在项目中的单个文件即可。一个简单的zip压缩文件应该可以正常工作,并且在需要访问源文件时很容易解压缩。文本压缩得很好,所以无论如何压缩它都是有意义的。例如,如果你不想使用zip,其他任何东西都会很好 - 例如XML文件。它甚至可以为您提供使用Roslyn之类的功能来提供语法突出显示以及所有必要的上下文。

反编译并不一定是一种可怕的方法。基本上,你正在交易CPU的内存。你会失去评论,但如果你的代码非常简单,那应该不是问题。方法参数保留他们的名字,但当地人不 - 你需要PDB,这是一个巨大的矫枉过正。它实际上取决于你正在进行的计算。但对于大多数情况来说,这可能不是最好的解决方案。

处理这个有点迂回的方式将是一个多文件T4模板。基本上,您将生成与源代码文件一样多的文件,并将它们作为嵌入式资源。我不确定这是多么简单,我确定不会包含代码:D

另一个(有点奇怪)选项是使用文件链接。只需像往常一样在项目中的源代码文件,但也做一个单独的文件夹,其中相同的文件将被添加使用“添加为链接”。内容将与实际的源代码共享,但您可以指定不同的构建操作 - 即Embedded Resource。这需要在添加或移动文件时进行少量的手动工作,但它相对简单。如果需要的话,这也可以是自动的,尽管这听起来像是过度杀伤。

我能想到的最干净的选项是添加一个新的构建操作 - 编译+嵌入。这要求您将构建目标文件添加到项目中,但实际上这很简单。目标文件只是一个XML文件,然后您只需手动编辑您的SLN/CSPROJ文件以将该目标包含在构建中,那么您就很好。棘手的部分是,您还需要强制Microsoft.CSharp.Core.target使用您的Compile + Embed操作作为源代码和嵌入式资源。这当然很容易通过手动更改目标文件来完成,但这是处理该问题的一种可怕方式。不过,我不确定这样做的最佳方式是什么。也许有一种方法可以将@(Compile)重新定义为@(Compile;MyCompileAndEmbed)?我知道通常的财产组是可能的,但我不确定这样的事情是否可以用“列表”来完成。

+0

保留注释和整个源代码是一个目标。我希望围绕这个功能提出任何问题以保证行准确性。所以保持评论/本地人完好是可取的。感谢您澄清PDB不包含任何来源。我知道这是异常代码跟踪所必需的。但认为它被包括在内。 (我完全知道该DLL不包含任何来源:-P) –

+0

@ BenFord它不是必需的异常跟踪本身。你将会看到的主要区别是没有PDB,你会得到一个类似这样的东西:'MyClass.MyMethod + 234',而使用PDB时,你会得到'MyClass.MyMethod:38'。在第一种情况下,数字是一个IL字节偏移量,在第二种情况下,它是一行代码。所以PDB使得调试变得更容易,但在生产中实际上并不需要,特别是如果您保留所有“生产”PDB的备份。我不知道如何轻松地从IL偏移量到行,但我只是使用WinDbg。 – Luaan