Description
Issue Description
TaskHostFactory
does not allow using public properties with private get accessor as task parameters.
Steps to Reproduce
A/A.cs
using Microsoft.Build.Utilities;
public sealed class SampleTask : Task
{
public string? S1 { private get; set; }
public string? S2 { get; set; }
public string? S3 { set { } }
public SampleTask() { }
public override bool Execute() => true;
}
A/A.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>Enable</Nullable>
<TargetFramework>net9.0</TargetFramework>
<OutDir>../out</OutDir>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Tasks.Core">
<Version>17.14.8</Version>
</PackageReference>
</ItemGroup>
</Project>
B/B.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>Enable</Nullable>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<UsingTask TaskName="SampleTask" TaskFactory="TaskHostFactory" AssemblyFile="../out/A.dll" Condition="$(UseTaskHost)=='True'" />
<UsingTask TaskName="SampleTask" AssemblyFile="../out/A.dll" Condition="$(UseTaskHost)=='False'" />
<Target Name="TestTarget" AfterTargets="Build">
<SampleTask S1="Value" Condition="$(TestParameter)=='S1'" />
<SampleTask S2="Value" Condition="$(TestParameter)=='S2'" />
<SampleTask S3="Value" Condition="$(TestParameter)=='S3'" />
</Target>
</Project>
Test.cmd
dotnet build A
dotnet build B -p:UseTaskHost=False -p:TestParameter=S1
dotnet build B -p:UseTaskHost=False -p:TestParameter=S2
dotnet build B -p:UseTaskHost=False -p:TestParameter=S3
dotnet build B -p:UseTaskHost=True -p:TestParameter=S1
dotnet build B -p:UseTaskHost=True -p:TestParameter=S2
dotnet build B -p:UseTaskHost=True -p:TestParameter=S3
Test.zip
Run Test.cmd
from zip file.
Expected Behavior
All calls to dotnet build
should be successful.
Actual Behavior
Call to dotnet build B -p:UseTaskHost=True -p:TestParameter=S1
fails with
Restore complete (0,7s)
B failed with 2 error(s) (0,5s) → B\bin\Debug\net9.0\B.dll
M:\Temp\Test\B\B.csproj(9,15): error MSB4064: The "S1" parameter is not supported by the "SampleTask" task loaded from assembly: A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null from the path: M:\Temp\Test\out\A.dll. Verify that the parameter exists on the task, the <UsingTask> points to the correct assembly, and it is a settable public instance property.
M:\Temp\Test\B\B.csproj(9,3): error MSB4063: The "SampleTask" task could not be initialized with its input parameters.
Build failed with 2 error(s) in 2,4s
Analysis
https://github.com/dotnet/msbuild/blob/4ad462496537cd497f9c43531acb21f44d58cd67/src/Shared/LoadedType.cs#L70
When assembly loaded via MetadataLoadContext
, then call to type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
will not return public properties with private get accessor. But when assembly loaded for execution, then such properties will be included.
Versions & Configurations
.NET SDK:
Version: 9.0.300
Commit: 15606fe0a8
Workload version: 9.0.300-manifests.c678e91b
MSBuild version: 17.14.5+edd3bbf37
Runtime Environment:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.300\
Host:
Version: 9.0.5
Architecture: x64
Commit: e36e4d1a8f
.NET SDKs installed:
9.0.300 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 9.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Metadata
Metadata
Assignees
Type
Projects
Status
No status