Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit 95835d6

Browse files
committed
Continue generating RelatedAssemblyPart on assembly if GenerateAssemblyInfo=false
Fixes #2257
1 parent 60b6ec0 commit 95835d6

File tree

7 files changed

+237
-158
lines changed

7 files changed

+237
-158
lines changed

src/Microsoft.AspNetCore.Mvc.Razor.Extensions/build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.targets

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
<Project>
22
<PropertyGroup>
3-
43
<!--
5-
MVC will generally want to add support for runtime compilation, but only for applications.
4+
Determines if the Sdk is allowed to add additional attributes to the project assembly.
5+
For instance, MVC will generally want to add attributes to support view discovery and runtime compilation.
66
-->
77
<GenerateRazorAssemblyInfo Condition="'$(GenerateRazorAssemblyInfo)'==''">true</GenerateRazorAssemblyInfo>
88

9+
<!--
10+
MVC will generally want to add support for runtime compilation, but only for applications.
11+
-->
912
<GenerateRazorHostingAssemblyInfo Condition="'$(GenerateRazorHostingAssemblyInfo)'=='' AND '$(OutputType)'=='exe'">$(GenerateRazorAssemblyInfo)</GenerateRazorHostingAssemblyInfo>
1013

1114
<!--
@@ -20,14 +23,14 @@
2023
</PropertyGroup>
2124

2225
<ItemGroup Condition="'$(GenerateRazorAssemblyInfo)'=='true' AND '$(ResolvedRazorCompileToolset)'=='RazorSdk' AND ('$(RazorCompileOnBuild)' == 'true' OR '$(RazorCompileOnPublish)' == 'true')">
23-
<AssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute">
26+
<_RazorAssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute">
2427
<_Parameter1>$(RazorTargetName)</_Parameter1>
25-
</AssemblyAttribute>
28+
</_RazorAssemblyAttribute>
2629
</ItemGroup>
2730

2831
<ItemGroup Condition="'$(GenerateProvideApplicationPartFactoryAttribute)' == 'true' AND '$(ProvideApplicationPartFactoryAttributeTypeName)'!=''">
29-
<RazorAssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ProvideApplicationPartFactoryAttribute">
32+
<RazorTargetAssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ProvideApplicationPartFactoryAttribute">
3033
<_Parameter1>$(ProvideApplicationPartFactoryAttributeTypeName)</_Parameter1>
31-
</RazorAssemblyAttribute>
34+
</RazorTargetAssemblyAttribute>
3235
</ItemGroup>
3336
</Project>

src/Microsoft.NET.Sdk.Razor/build/netstandard2.0/Microsoft.NET.Sdk.Razor.GenerateAssemblyInfo.targets

Lines changed: 96 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,53 +12,55 @@ Copyright (c) .NET Foundation. All rights reserved.
1212
<Project ToolsVersion="14.0">
1313
<PropertyGroup>
1414
<!-- Determines if the generated Razor assembly includes an auto-generated assembly info. -->
15-
<GenerateRazorTargetAssemblyInfo Condition="'$(GenerateRazorTargetAssemblyInfo)'==''">$(GenerateAssemblyInfo)</GenerateRazorTargetAssemblyInfo>
1615
<GenerateRazorTargetAssemblyInfo Condition="'$(GenerateRazorTargetAssemblyInfo)'==''">true</GenerateRazorTargetAssemblyInfo>
1716

1817
<!-- Set to true, to automatically include some AssemblyAttributes inferred from the project metadata in the generated Razor assembly -->
1918
<EnableDefaultRazorTargetAssemblyInfoAttributes Condition="'$(EnableDefaultRazorTargetAssemblyInfoAttributes)'==''">true</EnableDefaultRazorTargetAssemblyInfoAttributes>
2019

21-
<GeneratedRazorTargetAssemblyInfo Condition="'$(GeneratedRazorTargetAssemblyInfo)'==''">$(IntermediateOutputPath)$(MSBuildProjectName).RazorAssemblyInfo.cs</GeneratedRazorTargetAssemblyInfo>
20+
<!-- AssemblyInfo that gets added to the generated Razor dll -->
21+
<RazorTargetAssemblyInfo Condition="'$(RazorTargetAssemblyInfo)'==''">$(IntermediateOutputPath)$(MSBuildProjectName).RazorTargetAssemblyInfo.cs</RazorTargetAssemblyInfo>
22+
<_RazorTargetAssemblyInfoInputsCacheFile>$(IntermediateOutputPath)$(MSBuildProjectName).RazorTargetAssemblyInfo.cache</_RazorTargetAssemblyInfoInputsCacheFile>
2223

23-
<_GeneratedRazorAssemblyInfoInputsCacheFile>$(IntermediateOutputPath)$(MSBuildProjectName).RazorAssemblyInfoInputs.cache</_GeneratedRazorAssemblyInfoInputsCacheFile>
24+
<!-- AssemblyInfo that gets added to the project being compiled -->
25+
<_RazorAssemblyInfo>$(IntermediateOutputPath)$(MSBuildProjectName).RazorAssemblyInfo.cs</_RazorAssemblyInfo>
26+
<_RazorAssemblyInfoInputsCacheFile>$(IntermediateOutputPath)$(MSBuildProjectName).RazorAssemblyInfo.cache</_RazorAssemblyInfoInputsCacheFile>
2427
</PropertyGroup>
2528

2629
<PropertyGroup>
27-
<GenerateRazorAssemblyInfoDependsOn>
28-
GetRazorAssemblyAttributes;
29-
CreateRazorGeneratedAssemblyInfoInputsCacheFile;
30-
CoreGenerateRazorAssemblyInfo
31-
</GenerateRazorAssemblyInfoDependsOn>
30+
<GenerateRazorTargetAssemblyInfoDependsOn>
31+
GetRazorTargetAssemblyAttributes;
32+
_CreateRazorTargetAssemblyInfoInputsCacheFile;
33+
CoreGenerateRazorTargetAssemblyInfo
34+
</GenerateRazorTargetAssemblyInfoDependsOn>
3235
</PropertyGroup>
3336

3437
<Target
35-
Name="GenerateRazorAssemblyInfo"
36-
DependsOnTargets="$(GenerateRazorAssemblyInfoDependsOn)"
37-
Condition="'$(GenerateRazorTargetAssemblyInfo)'=='true'">
38+
Name="GenerateRazorTargetAssemblyInfo"
39+
DependsOnTargets="$(GenerateRazorTargetAssemblyInfoDependsOn)">
3840
</Target>
3941

4042
<Target
41-
Name="CoreGenerateRazorAssemblyInfo"
42-
Inputs="$(_GeneratedRazorAssemblyInfoInputsCacheFile)"
43-
Outputs="$(GeneratedRazorTargetAssemblyInfo)"
44-
Condition="'@(RazorCompile)'!=''">
43+
Name="CoreGenerateRazorTargetAssemblyInfo"
44+
Inputs="$(_RazorTargetAssemblyInfoInputsCacheFile)"
45+
Outputs="$(RazorTargetAssemblyInfo)"
46+
Condition="'$(GenerateRazorTargetAssemblyInfo)'=='true' AND '@(RazorCompile)'!=''">
4547

4648
<ItemGroup Condition="'$(GenerateRazorTargetAssemblyInfo)'=='true'">
4749
<!-- Ensure the generated assemblyinfo file is not already part of RazorCompile sources -->
48-
<RazorCompile Remove="$(GeneratedRazorTargetAssemblyInfo)" />
49-
<RazorCompile Include="$(GeneratedRazorTargetAssemblyInfo)" />
50+
<RazorCompile Remove="$(RazorTargetAssemblyInfo)" />
51+
<RazorCompile Include="$(RazorTargetAssemblyInfo)" />
5052
</ItemGroup>
5153

52-
<WriteCodeFragment AssemblyAttributes="@(RazorAssemblyAttribute)" Language="C#" OutputFile="$(GeneratedRazorTargetAssemblyInfo)" />
54+
<WriteCodeFragment AssemblyAttributes="@(RazorTargetAssemblyAttribute)" Language="C#" OutputFile="$(RazorTargetAssemblyInfo)" />
5355

5456
<ItemGroup>
55-
<FileWrites Include="$(GeneratedRazorTargetAssemblyInfo)" />
57+
<FileWrites Include="$(RazorTargetAssemblyInfo)" />
5658
</ItemGroup>
5759

5860
</Target>
5961

6062
<Target
61-
Name="GetRazorAssemblyAttributes"
63+
Name="GetRazorTargetAssemblyAttributes"
6264
DependsOnTargets="GetAssemblyVersion"
6365
Condition="'$(EnableDefaultRazorTargetAssemblyInfoAttributes)'=='true'">
6466

@@ -71,37 +73,37 @@ Copyright (c) .NET Foundation. All rights reserved.
7173
</PropertyGroup>
7274

7375
<ItemGroup>
74-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyCompanyAttribute" Condition="'$(Company)' != '' and '$(GenerateAssemblyCompanyAttribute)' == 'true'">
76+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyCompanyAttribute" Condition="'$(Company)' != '' and '$(GenerateAssemblyCompanyAttribute)' == 'true'">
7577
<_Parameter1>$(Company)</_Parameter1>
76-
</RazorAssemblyAttribute>
77-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyConfigurationAttribute" Condition="'$(Configuration)' != '' and '$(GenerateAssemblyConfigurationAttribute)' == 'true'">
78+
</RazorTargetAssemblyAttribute>
79+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyConfigurationAttribute" Condition="'$(Configuration)' != '' and '$(GenerateAssemblyConfigurationAttribute)' == 'true'">
7880
<_Parameter1>$(Configuration)</_Parameter1>
79-
</RazorAssemblyAttribute>
80-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyCopyrightAttribute" Condition="'$(Copyright)' != '' and '$(GenerateAssemblyCopyrightAttribute)' == 'true'">
81+
</RazorTargetAssemblyAttribute>
82+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyCopyrightAttribute" Condition="'$(Copyright)' != '' and '$(GenerateAssemblyCopyrightAttribute)' == 'true'">
8183
<_Parameter1>$(Copyright)</_Parameter1>
82-
</RazorAssemblyAttribute>
83-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyProductAttribute" Condition="'$(Product)' != '' and '$(GenerateAssemblyProductAttribute)' == 'true'">
84+
</RazorTargetAssemblyAttribute>
85+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyProductAttribute" Condition="'$(Product)' != '' and '$(GenerateAssemblyProductAttribute)' == 'true'">
8486
<_Parameter1>$(Product)</_Parameter1>
85-
</RazorAssemblyAttribute>
86-
<RazorAssemblyAttribute Include="System.Resources.NeutralResourcesLanguageAttribute" Condition="'$(NeutralLanguage)' != '' and '$(GenerateNeutralResourcesLanguageAttribute)' == 'true'">
87+
</RazorTargetAssemblyAttribute>
88+
<RazorTargetAssemblyAttribute Include="System.Resources.NeutralResourcesLanguageAttribute" Condition="'$(NeutralLanguage)' != '' and '$(GenerateNeutralResourcesLanguageAttribute)' == 'true'">
8789
<_Parameter1>$(NeutralLanguage)</_Parameter1>
88-
</RazorAssemblyAttribute>
90+
</RazorTargetAssemblyAttribute>
8991

90-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyDescriptionAttribute" Condition="'$(RazorAssemblyDescription)' != '' and '$(GenerateAssemblyDescriptionAttribute)' == 'true'">
92+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyDescriptionAttribute" Condition="'$(RazorAssemblyDescription)' != '' and '$(GenerateAssemblyDescriptionAttribute)' == 'true'">
9193
<_Parameter1>$(RazorAssemblyDescription)</_Parameter1>
92-
</RazorAssemblyAttribute>
93-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyFileVersionAttribute" Condition="'$(RazorAssemblyFileVersion)' != '' and '$(GenerateAssemblyFileVersionAttribute)' == 'true'">
94+
</RazorTargetAssemblyAttribute>
95+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyFileVersionAttribute" Condition="'$(RazorAssemblyFileVersion)' != '' and '$(GenerateAssemblyFileVersionAttribute)' == 'true'">
9496
<_Parameter1>$(RazorAssemblyFileVersion)</_Parameter1>
95-
</RazorAssemblyAttribute>
96-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyInformationalVersionAttribute" Condition="'$(RazorAssemblyInformationalVersion)' != '' and '$(GenerateAssemblyInformationalVersionAttribute)' == 'true'">
97+
</RazorTargetAssemblyAttribute>
98+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyInformationalVersionAttribute" Condition="'$(RazorAssemblyInformationalVersion)' != '' and '$(GenerateAssemblyInformationalVersionAttribute)' == 'true'">
9799
<_Parameter1>$(RazorAssemblyInformationalVersion)</_Parameter1>
98-
</RazorAssemblyAttribute>
99-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyTitleAttribute" Condition="'$(RazorAssemblyTitle)' != '' and '$(GenerateAssemblyTitleAttribute)' == 'true'">
100+
</RazorTargetAssemblyAttribute>
101+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyTitleAttribute" Condition="'$(RazorAssemblyTitle)' != '' and '$(GenerateAssemblyTitleAttribute)' == 'true'">
100102
<_Parameter1>$(RazorAssemblyTitle)</_Parameter1>
101-
</RazorAssemblyAttribute>
102-
<RazorAssemblyAttribute Include="System.Reflection.AssemblyVersionAttribute" Condition="'$(RazorAssemblyVersion)' != '' and '$(GenerateAssemblyVersionAttribute)' == 'true'">
103+
</RazorTargetAssemblyAttribute>
104+
<RazorTargetAssemblyAttribute Include="System.Reflection.AssemblyVersionAttribute" Condition="'$(RazorAssemblyVersion)' != '' and '$(GenerateAssemblyVersionAttribute)' == 'true'">
103105
<_Parameter1>$(RazorAssemblyVersion)</_Parameter1>
104-
</RazorAssemblyAttribute>
106+
</RazorTargetAssemblyAttribute>
105107
</ItemGroup>
106108

107109
</Target>
@@ -111,23 +113,73 @@ Copyright (c) .NET Foundation. All rights reserved.
111113
create a hash of all assembly attributes so that the cache file will change with the calculated
112114
assembly attribute values and msbuild will then execute CoreGenerateAssembly to generate a new file.
113115
-->
114-
<Target Name="CreateRazorGeneratedAssemblyInfoInputsCacheFile" Condition="'@(RazorAssemblyAttribute)' != ''">
116+
<Target Name="_CreateRazorTargetAssemblyInfoInputsCacheFile" Condition="'@(RazorTargetAssemblyAttribute)' != ''">
115117

116118
<!-- We only use up to _Parameter1 for most attributes, but other targets may add additional assembly attributes with multiple parameters. -->
117-
<Hash ItemsToHash="@(RazorAssemblyAttribute->'%(Identity)%(_Parameter1)%(_Parameter2)%(_Parameter3)%(_Parameter4)%(_Parameter5)%(_Parameter6)%(_Parameter7)%(_Parameter8)')">
119+
<Hash ItemsToHash="@(RazorTargetAssemblyAttribute->'%(Identity)%(_Parameter1)%(_Parameter2)%(_Parameter3)%(_Parameter4)%(_Parameter5)%(_Parameter6)%(_Parameter7)%(_Parameter8)')">
120+
<Output TaskParameter="HashResult" PropertyName="_RazorTargetAssemblyAttributesHash" />
121+
</Hash>
122+
123+
<WriteLinesToFile
124+
Lines="$(_RazorTargetAssemblyAttributesHash)"
125+
File="$(_RazorTargetAssemblyInfoInputsCacheFile)"
126+
Overwrite="True"
127+
WriteOnlyWhenDifferent="True" />
128+
129+
<ItemGroup>
130+
<FileWrites Include="$(_RazorTargetAssemblyInfoInputsCacheFile)" />
131+
</ItemGroup>
132+
133+
</Target>
134+
135+
<Target Name="_CreateRazorAssemblyInfoInputsCacheFile" Condition="'@(_RazorAssemblyAttribute)' != ''">
136+
137+
<!-- We only use up to _Parameter1 for most attributes, but other targets may add additional assembly attributes with multiple parameters. -->
138+
<Hash ItemsToHash="@(_RazorAssemblyAttribute->'%(Identity)%(_Parameter1)%(_Parameter2)%(_Parameter3)%(_Parameter4)%(_Parameter5)%(_Parameter6)%(_Parameter7)%(_Parameter8)')">
118139
<Output TaskParameter="HashResult" PropertyName="_RazorAssemblyAttributesHash" />
119140
</Hash>
120141

121142
<WriteLinesToFile
122143
Lines="$(_RazorAssemblyAttributesHash)"
123-
File="$(_GeneratedRazorAssemblyInfoInputsCacheFile)"
144+
File="$(_RazorAssemblyInfoInputsCacheFile)"
124145
Overwrite="True"
125146
WriteOnlyWhenDifferent="True" />
126147

127148
<ItemGroup>
128-
<FileWrites Include="$(_GeneratedRazorAssemblyInfoInputsCacheFile)" />
149+
<FileWrites Include="$(_RazorAssemblyInfoInputsCacheFile)" />
129150
</ItemGroup>
130151

131152
</Target>
132153

154+
<Target
155+
Name="_CoreGenerateRazorAssemblyInfo"
156+
DependsOnTargets="_CreateRazorAssemblyInfoInputsCacheFile"
157+
Inputs="$(_RazorAssemblyInfoInputsCacheFile)"
158+
Outputs="$(_RazorAssemblyInfo)"
159+
Condition="'@(_RazorAssemblyAttribute)' != ''">
160+
161+
<ItemGroup Condition="'$(GenerateRazorAssemblyInfo)'=='true'">
162+
<Compile Remove="$(_RazorAssemblyInfo)" />
163+
<Compile Include="$(_RazorAssemblyInfo)" />
164+
</ItemGroup>
165+
166+
<WriteCodeFragment AssemblyAttributes="@(_RazorAssemblyAttribute)" Language="$(Language)" OutputFile="$(_RazorAssemblyInfo)" />
167+
168+
<ItemGroup>
169+
<FileWrites Include="$(_RazorAssemblyInfo)" />
170+
</ItemGroup>
171+
172+
</Target>
173+
174+
<PropertyGroup>
175+
<!-- Generate attributes in the main assembly if we're targeting a C# project and using the Razor Sdk. -->
176+
<CoreCompileDependsOn Condition="'$(ResolvedRazorCompileToolset)'=='RazorSdk' and '$(Language)' == 'C#' and '$(GenerateRazorAssemblyInfo)' == 'true'">
177+
$(CoreCompileDependsOn);_GenerateRazorAssemblyInfo
178+
</CoreCompileDependsOn>
179+
180+
<_GenerateRazorAssemblyInfoDependsOn>PrepareForBuild;_CoreGenerateRazorAssemblyInfo</_GenerateRazorAssemblyInfoDependsOn>
181+
</PropertyGroup>
182+
183+
<Target Name="_GenerateRazorAssemblyInfo" DependsOnTargets="$(_GenerateRazorAssemblyInfoDependsOn)" />
184+
133185
</Project>

src/Microsoft.NET.Sdk.Razor/build/netstandard2.0/Sdk.Razor.CurrentVersion.targets

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Copyright (c) .NET Foundation. All rights reserved.
4747
<PrepareForRazorCompileDependsOn>
4848
RazorGenerate;
4949
ResolveRazorCompileInputs;
50-
GenerateRazorAssemblyInfo
50+
GenerateRazorTargetAssemblyInfo
5151
</PrepareForRazorCompileDependsOn>
5252

5353
<ResolveRazorCompileInputsDependsOn>
@@ -230,7 +230,7 @@ Copyright (c) .NET Foundation. All rights reserved.
230230
</Target>
231231

232232
<!--
233-
Generates assembly attributes in support for Razor runtime code generation. This is a set of standard
233+
Gets assembly attributes in support for Razor runtime code generation. This is a set of standard
234234
metadata attributes (defined in Microsoft.AspNetCore.Razor.Runtime) that capture the build-time
235235
Razor configuration of an application to be used at runtime.
236236
@@ -240,22 +240,25 @@ Copyright (c) .NET Foundation. All rights reserved.
240240
The SDK expects configurations that use runtime compilation to set $(GenerateRazorHostingAssemblyInfo) to true,
241241
it will be unset by default.
242242
-->
243+
<PropertyGroup>
244+
<_GenerateRazorAssemblyInfoDependsOn>RazorGetAssemblyAttributes;$(_GenerateRazorAssemblyInfoDependsOn)</_GenerateRazorAssemblyInfoDependsOn>
245+
</PropertyGroup>
246+
243247
<Target
244248
Name="RazorGetAssemblyAttributes"
245-
AfterTargets="GetAssemblyAttributes"
246249
Condition="'$(GenerateRazorHostingAssemblyInfo)'=='true' and '$(RazorDefaultConfiguration)'!=''"
247250
DependsOnTargets="ResolveRazorConfiguration">
248251
<ItemGroup>
249-
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute">
252+
<_RazorAssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute">
250253
<_Parameter1>$(RazorLangVersion)</_Parameter1>
251-
</AssemblyAttribute>
252-
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute">
254+
</_RazorAssemblyAttribute>
255+
<_RazorAssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute">
253256
<_Parameter1>$(RazorDefaultConfiguration)</_Parameter1>
254-
</AssemblyAttribute>
255-
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute" Condition="'%(ResolvedRazorExtension.AssemblyName)'!=''">
257+
</_RazorAssemblyAttribute>
258+
<_RazorAssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute" Condition="'%(ResolvedRazorExtension.AssemblyName)'!=''">
256259
<_Parameter1>%(ResolvedRazorExtension.Identity)</_Parameter1>
257260
<_Parameter2>%(ResolvedRazorExtension.AssemblyName)</_Parameter2>
258-
</AssemblyAttribute>
261+
</_RazorAssemblyAttribute>
259262
</ItemGroup>
260263

261264
</Target>

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
54
using System.Collections.Generic;
65
using System.IO;
76
using System.Linq;

0 commit comments

Comments
 (0)