简体   繁体   English

Visual Studio 一个带有多个 dll 作为输出的项目?

[英]Visual studio one project with several dlls as output?

I'm programming a project with plugin support.我正在编写一个支持插件的项目。 Since many of the plugins are relatively small (only one source-file/class) I would like to have them all in one project in visual studio, but to successfully do this I would need each source-file/class to be compiled into its own dll file, is this possible using visual studio?由于许多插件相对较小(只有一个源文件/类),我希望将它们全部放在 Visual Studio 的一个项目中,但要成功做到这一点,我需要将每个源文件/类编译成它的自己的 dll 文件,这可以使用 Visual Studio 吗?

If this is not possible with visual studio, would it be possible using another build system, while still coding and debugging with visual studio?如果 Visual Studio 无法做到这一点,是否可以使用另一个构建系统,同时仍然使用 Visual Studio 进行编码和调试?

Currently I've set the plugins project output type to console, and programmed a main() method that will compile all .cs files in the source directory to dlls and copy those to the proper directory.目前,我已将插件项目输出类型设置为控制台,并编写了一个 main() 方法,该方法会将源目录中的所有 .cs 文件编译为 dll 并将它们复制到正确的目录中。 Then I set that console app to be the post-build event of the plugins project.然后我将该控制台应用程序设置为插件项目的构建后事件。 It works, but it seems like a very ugly hack.它有效,但它似乎是一个非常丑陋的黑客。

Using visual studio 2010.使用 Visual Studio 2010。

You could create one project for each plugin and group all projects in a solution.您可以为每个插件创建一个项目并将所有项目分组到一个解决方案中。

If you don't want to have one project per plugin, you could create a custom build with MSBuild using CSC task如果您不希望每个插件有一个项目,您可以使用CSC 任务使用 MSBuild 创建自定义构建

How to generate a dll for each plugin file如何为每个插件文件生成一个dll

  1. In a project you add all plugins files在项目中添加所有插件文件

  2. Edit the project file to specify which class will generate a plugin library :编辑项目文件以指定哪个类将生成插件库:

     <ItemGroup> <Compile Include="Class1.cs"> <Plugin>true</Plugin> </Compile> <Compile Include="Class2.cs" /> <Compile Include="Class3.cs"> <Plugin>true</Plugin> </Compile> <Compile Include="Program.cs" /> <Compile Include="Properties\\AssemblyInfo.cs" /> </ItemGroup>
  3. Add a new target in your project file to generate the plugins library在您的项目文件中添加一个新目标以生成插件库

    <Target Name="BuildPlugins"> <CSC Condition="%(Compile.Plugin) == 'true'" Sources="%(Compile.FullPath)" TargetType="library" OutputAssembly="$(OutputPath)%(Compile.FileName).dll" EmitDebugInformation="true" /> </Target>
  4. If you want to create the plugins library after each build, add an after build target :如果要在每次构建后创建插件库,请添加构建后目标:

     <Target Name="AfterBuild" DependsOnTargets="BuildPlugins"> </Target>

You just have to create a Solution then add as many projects you want.您只需要创建一个Solution然后添加任意数量的项目即可。

You can have like 5 Class Library projects and compile them, generating 5 DLLs.您可以拥有 5 个Class Library项目并编译它们,生成 5 个 DLL。

To expand upon Julien Hoarau's answer above, here is a solution that allows you to compile multiple DLL files from within a single project, and have those DLL files be compiled from multiple CS files.为了扩展上面 Julien Hoarau 的回答,这里有一个解决方案,它允许您从单个项目中编译多个 DLL 文件,并从多个 CS 文件编译这些 DLL 文件。 Just open your csproj file and add this before the </Project> tag:只需打开您的 csproj 文件并将其添加到 </Project> 标记之前:

  <!-- Plugin Building -->
  <!-- 1. Hardlink to NuGet References - CSC does not read HintPaths, so you will have to create these for all your packages -->
  <ItemGroup>
    <PluginReference Include="..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll" ><InProject>false</InProject></PluginReference>
    <PluginReference Include="..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll" ><InProject>false</InProject></PluginReference>
    <PluginReference Include="..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll" ><InProject>false</InProject></PluginReference>
    <PluginReference Include="..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll" ><InProject>false</InProject></PluginReference>
    <PluginReference Include="..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll" ><InProject>false</InProject></PluginReference>       
  </ItemGroup>
  <!-- 2. Each Plugin CS Files -->
  <!-- You see that each tag in here has it's own name starting with Plugin -->
  <!-- We can reference that later e.g. as @(PluginBlue) to get an array list to pass to the CSC sources, allowing us to have multiple files -->
  <!-- Plugin.Blue\**\*.cs gets all the files in the "Plugin.Blue" folder -->
  <!-- Plugin.Green just has a specific file list -->
  <ItemGroup>
    <PluginBlue Include="Plugin.Blue\**\*.cs"><InProject>false</InProject></PluginBlue>
    <PluginGreen Include="Plugin.Green\File1.cs"><InProject>false</InProject></PluginGreen>
    <PluginGreen Include="Plugin.Green\File2.cs"><InProject>false</InProject></PluginGreen>
  </ItemGroup>
  <!-- 3. Build each Plugin -->
  <Target Name="BuildPlugins">
    <!-- Plugin Blue -->
    <CSC Sources="@(PluginBlue)" References="@(PluginReference)" TargetType="library" OutputAssembly="$(OutputPath)Plugin.Blue.dll" EmitDebugInformation="true" />
    <!-- Plugin Green -->
    <CSC Sources="@(PluginGreen)" References="@(PluginReference)" TargetType="library" OutputAssembly="$(OutputPath)Plugin.Green.dll" EmitDebugInformation="true" />
  </Target>

  <!-- 4. Require Build on Solution Compile -->
  <Target Name="AfterBuild" DependsOnTargets="BuildPlugins">
  </Target>

This is my approach - it lets you keep everything organized at the bottom instead of spread out throughout the project file.这是我的方法 - 它可以让您将所有内容组织在底部,而不是分散在整个项目文件中。 Using使用

<InProject>false</InProject>

allows us to hide the files from the SolutionExplorer, and have a separate defined list of files instead of simply adding the plugin tag to the files we want.允许我们从 SolutionExplorer 隐藏文件,并有一个单独定义的文件列表,而不是简单地将插件标签添加到我们想要的文件中。 In your main solution, be sure to set the Build Action to "none" on all the files you are compiling in the plugin so there is no duplication in the main project file.在您的主要解决方案中,确保在您在插件中编译的所有文件上将 Build Action 设置为“none”,以便主项目文件中没有重复。

Some more reading about CSC:关于 CSC 的更多阅读:

https://msdn.microsoft.com/en-us/library/78f4aasd.aspx Command-line Building With csc.exe https://msdn.microsoft.com/en-us/library/78f4aasd.aspx使用 csc.exe 构建命令行

https://msdn.microsoft.com/en-us/library/ms379563(v=vs.80).aspx Working with the C# 2.0 Command Line Compiler https://msdn.microsoft.com/en-us/library/ms379563(v=vs.80).aspx使用 C# 2.0 命令行编译器

https://msdn.microsoft.com/en-us/library/s5c8athz.aspx Csc Task https://msdn.microsoft.com/en-us/library/s5c8athz.aspx Csc 任务

https://msdn.microsoft.com/en-us/library/7szfhaft.aspx MSBuild Conditions https://msdn.microsoft.com/en-us/library/7szfhaft.aspx MSBuild 条件

I hope this is useful to someone.我希望这对某人有用。

Some poetry:几首诗:

In my case - I needed to have plugin dlls built for the unit test project specifically.. If you do it the "normal way", by creating separate project for each plugin - then you will end up having more unit-test related projects than core assemblies.. So I think that in some cases it is worth doing multi-builds within same project.在我的情况下 - 我需要专门为unit test项目构建插件dlls ..核心程序集.. 所以我认为在某些情况下值得在同一个项目中进行多次构建。 With that being said - I would like to provide an improved version of the accepted answer.话虽如此 - 我想提供已接受答案的改进版本。

New approach improvements:新方法改进:

  • support for new SDK projects (used in .net Core)支持新的SDK项目(在 .net Core 中使用)
  • support to build assemblies that are referencing another projects within solution!支持构建引用解决方案中另一个项目的程序集!

Create a new empty library project, make sure that the structure is following:创建一个新的空库项目,确保结构如下:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>
</Project>

hint: you can create .Net core project and change the target to net472 , for example.提示:例如,您可以创建 .Net core 项目并将目标更改为net472

Add a plugin and some references if needed, then, per following documentation, add: https://docs.microsoft.com/en-us/dotnet/core/tools/csproj如果需要,添加插件和一些参考,然后根据以下文档添加: https : //docs.microsoft.com/en-us/dotnet/core/tools/csproj

<EnableDefaultCompileItems>false</EnableDefaultCompileItems>

This will make it possible to manually include files for building.. otherwise the build will include all files by default.这将使手动包含用于构建的文件成为可能。否则构建将默认包含所有文件。

Then explicitly add the item to be compiled:然后显式添加要编译的项目:

<ItemGroup>
<Compile Include="TestApp1.cs">
  <Plugin>true</Plugin>
</Compile>
</ItemGroup>

Then, as mentioned in the following source - you can aggregate all references into a single string: How to get paths to all referenced DLLs in MSBuild?然后,如以下来源所述 - 您可以将所有引用聚合到一个字符串中: 如何获取 MSBuild 中所有引用 DLL 的路径?

  <Target Name="GatherReferences" DependsOnTargets="ResolveReferences">
    <ItemGroup>
      <MyReferencedAssemblies Include="@(ReferencePath)" />
    </ItemGroup>
  </Target>

To test:测试:

  <Target Name="TestMessage" AfterTargets="Build" >
    <Message Text="Referenced assemblies: @(ReferencePath)" Importance="high"/>
  </Target>

Then you have to append a build target that is triggered on PostBuild:然后你必须附加一个在 PostBuild 上触发的构建目标:

  <Target Name="BuildPlugins" AfterTargets="PostBuildEvent">
    <CSC Condition="%(Compile.Plugin) == 'true'"
         Sources="%(Compile.FullPath)"
         TargetType="library"
         References="@(ReferencePath)"
         OutputAssembly="$(OutputPath)%(Compile.FileName).dll"
         EmitDebugInformation="true" />
  </Target>

The difference here you will notice is a References property which basically translates the value into appropriate -reference argument for CSC compiler: https://docs.microsoft.com/en-us/visualstudio/msbuild/csc-task?view=vs-2019您会注意到这里的区别是References属性,它基本上将值转换为 CSC 编译器的适当 -reference 参数: https ://docs.microsoft.com/en-us/visualstudio/msbuild/csc-task?view=vs- 2019年

bonus: you might incorporate this logic into your project even without having to explicitly define the Plugin property..奖励:即使不必显式定义Plugin属性,您也可以将此逻辑合并到您的项目中。

According to this topic here: MsBuild Condition Evaluate Property Contains根据这里的主题: MsBuild Condition Evaluate Property Contains

It is possible to use Regex expression on build metadata: https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2019可以在构建元数据上使用正则表达式: https ://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2019

So basically, something like this is allowed:所以基本上,这样的事情是允许的:

Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Compile.Filename)', 'Plugin'))"

You can make it so, that if the Class filename contains a specific keyword , then you can trigger a separate compilation for such file.. Or if the file is l ocated in specific folder !您可以这样做,如果类文件名包含特定关键字,那么您可以触发此类文件的单独编译。或者如果文件位于特定文件夹中 In example above if the file has word "Plugin" in it, then it will get picked up by CSC task.. I recommend checking metadata page to see all options.在上面的例子中,如果文件中有“插件”这个词,那么它会被 CSC 任务选中。我建议检查元数据页面以查看所有选项。

bonus: If you just like me like being able to step up into the code and also to be able to output into the Debug output window, you can also define:奖励:如果您像我一样喜欢能够进入代码并能够输出到Debug输出窗口,您还可以定义:

  DefineConstants="DEBUG;TRACE"
  DebugType="full"

My latest configuration looks like this:我的最新配置是这样的:

  <Target Name="BuildPlugins" AfterTargets="PostBuildEvent">
    <CSC 
      Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Compile.FullPath)', '.*\\AppUnitTests\\Plugins\\.*.cs'))"
      Sources="%(Compile.FullPath)" 
      TargetType="library" 
      References="@(ReferencePath)"
      OutputAssembly="$(OutputPath)Plugins\%(Compile.FileName).dll" 
      EmitDebugInformation="true"
      DefineConstants="DEBUG;TRACE"
      DebugType="full" />
  </Target>

Hopefully it was useful for someone ;)希望它对某人有用;)

ps my thanks to original author for giving an example that I could improve upon. ps 感谢原作者提供了一个我可以改进的例子。

If you want each code file to be it's own DLL, then you have to make a new project for each code file.如果您希望每个代码文件都是它自己的 DLL,那么您必须为每个代码文件创建一个新项目。 But you can put multiple project files (.csproj) into one big solution.但是您可以将多个项目文件 (.csproj) 放入一个大解决方案中。

If this doesn't suite you, then you could always compile your project using the command line.如果这不适合您,那么您始终可以使用命令行编译您的项目。 That would allow you to customize your build to suite your needs.这将允许您自定义构建以满足您的需求。 For instance you could write a batch scrip, or a powershell script that would compile all your code files into a separate DLL.例如,您可以编写批处理脚本或将所有代码文件编译为单独 DLL 的 powershell 脚本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM