如果Visual Studio无法实现此功能,是否可以使用其他构建系统,在使用Visual Studio进行编码和调试的同时实现此目标?
当前,我已经将插件项目的输出类型设置为控制台,并编写了一个main()方法,将源目录中的所有.cs文件编译为dll并将其复制到正确的目录。然后,我将该控制台应用程序设置为插件项目的后生成事件。它能够工作,但看起来像是一个非常丑陋的 hack。
使用Visual Studio 2010。
In a project you add all plugins files
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>
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>
If you want to create the plugins library after each build, add an after build target :
<Target Name="AfterBuild" DependsOnTargets="BuildPlugins">
</Target>
您只需 创建一个Solution
,然后添加尽可能多的项目。
您可以拥有5个 Class Library
项目并编译它们,生成5个DLL文件。
<!-- 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”中隐藏,并拥有一个单独定义的文件列表,而不仅仅是添加插件标签到我们想要的文件中。在您的主解决方案中,请确保将所有编译插件中的文件的“Build Action”设置为“none”,以便主项目文件中没有重复。
关于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 条件
我希望这对某人有用。
一些诗:
就我而言 - 我需要为单元测试
项目专门构建插件dlls
。如果您按照“正常方式”进行,为每个插件创建单独的项目 - 那么您最终会拥有比核心程序集更多与单元测试相关的项目。因此,我认为在某些情况下,在同一项目中进行多次构建是值得的。话虽如此 - 我想提供一个改进版本的已接受答案。
新方法的改进:
SDK
项目(用于.net Core)创建一个新的空库项目,请确保其结构遵循以下格式:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
</Project>
提示: 例如,您可以创建 .Net Core 项目并将目标更改为 net472
。
如果需要,添加插件和一些引用,然后根据以下文档添加: https://learn.microsoft.com/en-us/dotnet/core/tools/csproj
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<ItemGroup>
<Compile Include="TestApp1.cs">
<Plugin>true</Plugin>
</Compile>
</ItemGroup>
接下来,如下面的来源所述 - 您可以将所有引用聚合到单个字符串中:如何在MSBuild中获取所有引用DLL的路径?
<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>
Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Compile.Filename)', 'Plugin'))"
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>