我正在编写一个支持插件的项目。 由于许多插件相对较小(只有一个源文件/类),我希望将它们全部放在visual studio中的一个项目中,但为了成功完成这个,我需要将每个源文件/类编译到其中自己的dll文件,这可能使用visual studio吗?
如果使用visual studio无法实现这一点,是否可以使用其他构建系统,同时仍可使用visual studio进行编码和调试?
目前我已将插件项目输出类型设置为console,并编写了一个main()方法,该方法将源目录中的所有.cs文件编译为dll并将其复制到正确的目录中。然后我将该控制台应用程序设置为插件项目的后期构建事件。它有效,但它似乎是一个非常难看的黑客。
使用visual studio 2010。
答案 0 :(得分:36)
您可以为每个插件创建一个项目,并将解决方案中的所有项目分组。
如果您不希望每个插件都有一个项目,可以使用CSC task
使用MSBuild创建自定义版本编辑项目文件以指定哪个类将生成插件库:
<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>
在项目文件中添加新目标以生成插件库
<Target Name="BuildPlugins">
<CSC Condition="%(Compile.Plugin) == 'true'"
Sources="%(Compile.FullPath)"
TargetType="library"
OutputAssembly="$(OutputPath)%(Compile.FileName).dll"
EmitDebugInformation="true" />
</Target>
如果要在每次构建后创建插件库,请添加后构建目标:
<Target Name="AfterBuild" DependsOnTargets="BuildPlugins">
</Target>
答案 1 :(得分:11)
您只需要create a Solution
然后添加所需的项目。
您可以拥有5个Class Library
个项目并进行编译,生成5个DLL。
答案 2 :(得分:3)
为了扩展Julien Hoarau的上述答案,这里有一个解决方案,允许您从单个项目中编译多个DLL文件,并从多个CS文件中编译这些DLL文件。只需打开您的csproj文件,然后在&lt; / Project&gt;之前添加它。标记:
<!-- 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>
这是我的方法 - 它允许您将所有内容组织在底部,而不是在整个项目文件中展开。使用
<InProject>false</InProject>
允许我们隐藏SolutionExplorer中的文件,并拥有单独定义的文件列表,而不是简单地将插件标记添加到我们想要的文件中。在您的主要解决方案中,请务必将构建操作设置为&#34;无&#34;在您正在插件中编译的所有文件上,因此主项目文件中没有重复。
关于CSC的更多阅读:
https://msdn.microsoft.com/en-us/library/78f4aasd.aspx使用csc.exe进行命令行构建
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任务
https://msdn.microsoft.com/en-us/library/7szfhaft.aspx MSBuild条件
我希望这对某人有用。
答案 3 :(得分:1)
一些诗歌:
在我的情况下-我需要专门为dlls
项目构建插件unit test
。如果您以“正常方式”进行操作,则为每个插件创建单独的项目-那么您将最终比核心程序集拥有更多的与单元测试相关的项目。因此,我认为在某些情况下,在同一项目中进行多次构建是值得的。话虽如此-我想提供接受答案的改进版本。
新方法的改进:
SDK
项目(在.net Core中使用)创建一个新的空库项目,确保结构如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
</Project>
提示::例如,您可以创建.Net核心项目并将目标更改为net472
。
根据需要添加一个插件和一些参考,然后根据以下文档添加: https://docs.microsoft.com/en-us/dotnet/core/tools/csproj
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
这将使得可以手动包括用于构建的文件。否则,默认情况下,构建将包括所有文件。
然后显式添加要编译的项目:
<ItemGroup>
<Compile Include="TestApp1.cs">
<Plugin>true</Plugin>
</Compile>
</ItemGroup>
然后,如以下源中所述-您可以将所有引用聚合为一个字符串:How to get paths to all referenced DLLs in MSBuild?
<Target Name="GatherReferences" DependsOnTargets="ResolveReferences">
<ItemGroup>
<MyReferencedAssemblies Include="@(ReferencePath)" />
</ItemGroup>
</Target>
要测试:
<Target Name="TestMessage" AfterTargets="Build" >
<Message Text="Referenced assemblies: @(ReferencePath)" Importance="high"/>
</Target>
然后,您必须附加在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>
您将在这里注意到的区别是References
属性,该属性基本上将值转换为CSC编译器的适当-reference参数:https://docs.microsoft.com/en-us/visualstudio/msbuild/csc-task?view=vs-2019
奖金::即使不必显式定义Plugin
属性,您也可以将此逻辑合并到项目中。
根据此处的主题:MsBuild Condition Evaluate Property Contains
可以在构建元数据上使用正则表达式:https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2019
所以基本上,这样的事情是允许的:
Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Compile.Filename)', 'Plugin'))"
您可以这样做,如果类文件名包含特定的关键字,则可以触发该文件的单独编译。或者如果文件是特定的文件夹!在上面的示例中,如果文件中包含单词“ Plugin”,则它将由CSC任务提取。.我建议检查元数据页面以查看所有选项。
奖金::如果您像我一样喜欢能够进入代码并能够输出到Debug
输出窗口,则还可以定义:
DefineConstants="DEBUG;TRACE"
DebugType="full"
我的最新配置如下:
<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>
希望它对某人有用;)
p.s。感谢原始作者提供了一个可以改进的示例。
答案 4 :(得分:-1)
如果您希望每个代码文件都是它自己的DLL,那么您必须为每个代码文件创建一个新项目。但是您可以将多个项目文件(.csproj)放入一个大解决方案中。
如果这不适合你,那么你总是可以使用命令行编译你的项目。这样您就可以自定义构建以满足您的需求。例如,您可以编写批处理脚本或PowerShell脚本,将所有代码文件编译为单独的DLL。