diff --git a/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs b/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
index ffd6ed0068e..fa6883c1c34 100644
--- a/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
@@ -32,10 +32,7 @@ public class AssemblyTaskFactory_Tests
///
private AssemblyLoadInfo _loadInfo;
- ///
- /// The loaded type from the initialized task factory.
- ///
- private LoadedType _loadedType;
+ private Dictionary _taskFactoryIdentityParameters = null;
///
/// Initialize a task factory
@@ -55,8 +52,8 @@ public void NullLoadInfo()
{
Assert.Throws(() =>
{
- AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
- taskFactory.InitializeFactory(null, "TaskToTestFactories", new Dictionary(), string.Empty, null, false, null, ElementLocation.Create("NONE"), String.Empty);
+ AssemblyTaskFactory taskFactory = new();
+ taskFactory.InitializeFactory(null, "TaskToTestFactories", new Dictionary(), string.Empty, ref _taskFactoryIdentityParameters, false, null, ElementLocation.Create("NONE"), String.Empty);
}
);
}
@@ -69,7 +66,7 @@ public void NullTaskName()
Assert.Throws(() =>
{
AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
- taskFactory.InitializeFactory(_loadInfo, null, new Dictionary(), string.Empty, null, false, null, ElementLocation.Create("NONE"), String.Empty);
+ taskFactory.InitializeFactory(_loadInfo, null, new Dictionary(), string.Empty, ref _taskFactoryIdentityParameters, false, null, ElementLocation.Create("NONE"), String.Empty);
}
);
}
@@ -82,7 +79,7 @@ public void EmptyTaskName()
Assert.Throws(() =>
{
AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
- taskFactory.InitializeFactory(_loadInfo, String.Empty, new Dictionary(), string.Empty, null, false, null, ElementLocation.Create("NONE"), String.Empty);
+ taskFactory.InitializeFactory(_loadInfo, String.Empty, new Dictionary(), string.Empty, ref _taskFactoryIdentityParameters, false, null, ElementLocation.Create("NONE"), String.Empty);
}
);
}
@@ -95,7 +92,7 @@ public void GoodTaskNameButNotInInfo()
Assert.Throws(() =>
{
AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
- taskFactory.InitializeFactory(_loadInfo, "RandomTask", new Dictionary(), string.Empty, null, false, null, ElementLocation.Create("NONE"), String.Empty);
+ taskFactory.InitializeFactory(_loadInfo, "RandomTask", new Dictionary(), string.Empty, ref _taskFactoryIdentityParameters, false, null, ElementLocation.Create("NONE"), String.Empty);
}
);
}
@@ -180,7 +177,7 @@ public void CreatableByTaskFactoryNullTaskName()
[Fact]
public void CreatableByTaskFactoryMatchingIdentity()
{
- IDictionary factoryIdentityParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary factoryIdentityParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
factoryIdentityParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.currentRuntime);
factoryIdentityParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.currentArchitecture);
@@ -200,7 +197,7 @@ public void CreatableByTaskFactoryMatchingIdentity()
[Fact]
public void CreatableByTaskFactoryMismatchedIdentity()
{
- IDictionary factoryIdentityParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary factoryIdentityParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
factoryIdentityParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.clr2);
factoryIdentityParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.currentArchitecture);
@@ -342,7 +339,7 @@ public void VerifyMatchingUsingTaskParametersDontLaunchTaskHost1()
ITask createdTask = null;
try
{
- IDictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
taskParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.any);
taskParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.any);
@@ -375,7 +372,7 @@ public void VerifyMatchingUsingTaskParametersDontLaunchTaskHost2()
ITask createdTask = null;
try
{
- IDictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
taskParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.any);
taskParameters.Add(XMakeAttributes.architecture, XMakeAttributes.GetCurrentMSBuildArchitecture());
@@ -408,7 +405,7 @@ public void VerifyMatchingParametersDontLaunchTaskHost()
ITask createdTask = null;
try
{
- IDictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
factoryParameters.Add(XMakeAttributes.runtime, XMakeAttributes.GetCurrentMSBuildRuntime());
SetupTaskFactory(factoryParameters, false /* don't want task host */);
@@ -444,7 +441,7 @@ public void VerifyNonmatchingUsingTaskParametersLaunchTaskHost()
ITask createdTask = null;
try
{
- IDictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
taskParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.clr2);
taskParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.any);
@@ -510,7 +507,7 @@ public void VerifyNonmatchingParametersLaunchTaskHost()
ITask createdTask = null;
try
{
- IDictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
factoryParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.clr2);
SetupTaskFactory(factoryParameters, false /* don't want task host */);
@@ -575,7 +572,7 @@ public void VerifyExplicitlyLaunchTaskHostEvenIfParametersMatch1()
ITask createdTask = null;
try
{
- IDictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary taskParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
taskParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.any);
taskParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.any);
@@ -641,7 +638,7 @@ public void VerifyExplicitlyLaunchTaskHostEvenIfParametersMatch2()
public void VerifySameFactoryCanGenerateDifferentTaskInstances()
{
ITask createdTask = null;
- IDictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary factoryParameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
factoryParameters.Add(XMakeAttributes.runtime, XMakeAttributes.MSBuildRuntimeValues.any);
factoryParameters.Add(XMakeAttributes.architecture, XMakeAttributes.MSBuildArchitectureValues.any);
@@ -694,7 +691,7 @@ public void VerifySameFactoryCanGenerateDifferentTaskInstances()
/// Abstract out the creation of the new AssemblyTaskFactory with default task, and
/// with some basic validation.
///
- private void SetupTaskFactory(IDictionary factoryParameters, bool explicitlyLaunchTaskHost)
+ private void SetupTaskFactory(Dictionary factoryParameters, bool explicitlyLaunchTaskHost)
{
_taskFactory = new AssemblyTaskFactory();
#if FEATURE_ASSEMBLY_LOCATION
@@ -702,8 +699,8 @@ private void SetupTaskFactory(IDictionary factoryParameters, boo
#else
_loadInfo = AssemblyLoadInfo.Create(typeof(TaskToTestFactories).GetTypeInfo().Assembly.FullName, null);
#endif
- _loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, null, ElementLocation.Create("NONE"), String.Empty);
- Assert.True(_loadedType.Assembly.Equals(_loadInfo)); // "Expected the AssemblyLoadInfo to be equal"
+ TypeInformation typeInfo = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary(), string.Empty, ref factoryParameters, explicitlyLaunchTaskHost, null, ElementLocation.Create("NONE"), String.Empty);
+ typeInfo.LoadInfo.ShouldBe(_loadInfo, "Expected the AssemblyLoadInfo to be equal");
}
#endregion
diff --git a/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs b/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
index 4482dda9bfa..1567868e60e 100644
--- a/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
@@ -1170,7 +1170,7 @@ private void InitializeHost(bool throwOnExecute)
TaskBuilderTestTask.TaskBuilderTestTaskFactory taskFactory = new TaskBuilderTestTask.TaskBuilderTestTaskFactory();
taskFactory.ThrowOnExecute = throwOnExecute;
string taskName = "TaskBuilderTestTask";
- (_host as TaskExecutionHost)._UNITTESTONLY_TaskFactoryWrapper = new TaskFactoryWrapper(taskFactory, loadedType, taskName, null);
+ (_host as TaskExecutionHost)._UNITTESTONLY_TaskFactoryWrapper = new TaskFactoryWrapper(taskFactory, new TypeInformation(loadedType), taskName, null);
_host.InitializeForTask
(
this,
diff --git a/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs b/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
index fd733207795..600eb2a81c5 100644
--- a/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
+++ b/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
@@ -257,12 +257,12 @@ void ITaskExecutionHost.InitializeForTask(IBuildEngine2 buildEngine, TargetLoggi
TaskRequirements requirements = TaskRequirements.None;
- if (_taskFactoryWrapper.TaskFactoryLoadedType.HasSTAThreadAttribute())
+ if (_taskFactoryWrapper.TaskFactoryTypeInformation.HasSTAThreadAttribute)
{
requirements |= TaskRequirements.RequireSTAThread;
}
- if (_taskFactoryWrapper.TaskFactoryLoadedType.HasLoadInSeparateAppDomainAttribute())
+ if (_taskFactoryWrapper.TaskFactoryTypeInformation.HasLoadInSeparateAppDomainAttribute)
{
requirements |= TaskRequirements.RequireSeparateAppDomain;
@@ -299,7 +299,7 @@ bool ITaskExecutionHost.InitializeForBatch(TaskLoggingContext loggingContext, It
if (_resolver == null)
{
_resolver = new TaskEngineAssemblyResolver();
- _resolver.Initialize(_taskFactoryWrapper.TaskFactoryLoadedType.Assembly.AssemblyFile);
+ _resolver.Initialize(_taskFactoryWrapper.TaskFactoryTypeInformation.LoadInfo.AssemblyFile);
_resolver.InstallHandler();
}
#endif
@@ -899,15 +899,18 @@ private TaskFactoryWrapper FindTaskInRegistry(IDictionary taskId
}
}
+ string taskFactoryFullName = returnClass.TaskFactory is AssemblyTaskFactory atf ? atf.TaskName : returnClass.TaskFactory.TaskType.FullName;
// Map to an intrinsic task, if necessary.
- if (String.Equals(returnClass.TaskFactory.TaskType.FullName, "Microsoft.Build.Tasks.MSBuild", StringComparison.OrdinalIgnoreCase))
+ if (String.Equals(taskFactoryFullName, "Microsoft.Build.Tasks.MSBuild", StringComparison.OrdinalIgnoreCase))
{
- returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(MSBuild)), new LoadedType(typeof(MSBuild), AssemblyLoadInfo.Create(typeof(TaskExecutionHost).GetTypeInfo().Assembly.FullName, null)), _taskName, null);
+ AssemblyLoadInfo loadInfo = AssemblyLoadInfo.Create(typeof(TaskExecutionHost).GetTypeInfo().Assembly.FullName, null);
+ returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(MSBuild)), new TypeInformation(new LoadedType(typeof(MSBuild), loadInfo)), _taskName, null);
_intrinsicTasks[_taskName] = returnClass;
}
- else if (String.Equals(returnClass.TaskFactory.TaskType.FullName, "Microsoft.Build.Tasks.CallTarget", StringComparison.OrdinalIgnoreCase))
+ else if (String.Equals(taskFactoryFullName, "Microsoft.Build.Tasks.CallTarget", StringComparison.OrdinalIgnoreCase))
{
- returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(CallTarget)), new LoadedType(typeof(CallTarget), AssemblyLoadInfo.Create(typeof(TaskExecutionHost).GetTypeInfo().Assembly.FullName, null)), _taskName, null);
+ AssemblyLoadInfo loadInfo = AssemblyLoadInfo.Create(typeof(TaskExecutionHost).GetTypeInfo().Assembly.FullName, null);
+ returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(CallTarget)), new TypeInformation(new LoadedType(typeof(CallTarget), loadInfo)), _taskName, null);
_intrinsicTasks[_taskName] = returnClass;
}
}
@@ -1073,30 +1076,15 @@ out parameterSet
else
{
// flag an error if we find a parameter that has no .NET property equivalent
- if (_taskFactoryWrapper.TaskFactoryLoadedType.LoadedAssembly is null)
- {
- _taskLoggingContext.LogError
- (
- new BuildEventFileInfo( parameterLocation ),
- "UnexpectedTaskAttribute",
- parameterName,
- _taskName,
- _taskFactoryWrapper.TaskFactoryLoadedType.Type.Assembly.FullName,
- _taskFactoryWrapper.TaskFactoryLoadedType.Type.Assembly.Location
- );
- }
- else
- {
- _taskLoggingContext.LogError
- (
- new BuildEventFileInfo( parameterLocation ),
- "UnexpectedTaskAttribute",
- parameterName,
- _taskName,
- _taskFactoryWrapper.TaskFactoryLoadedType.LoadedAssembly.FullName,
- _taskFactoryWrapper.TaskFactoryLoadedType.LoadedAssembly.Location
- );
- }
+ _taskLoggingContext.LogError
+ (
+ new BuildEventFileInfo( parameterLocation ),
+ "UnexpectedTaskAttribute",
+ parameterName,
+ _taskName,
+ _taskFactoryWrapper.TaskFactoryTypeInformation.LoadInfo.AssemblyName,
+ _taskFactoryWrapper.TaskFactoryTypeInformation.LoadInfo.AssemblyLocation
+ );
}
}
catch (AmbiguousMatchException)
diff --git a/src/Build/Instance/ReflectableTaskPropertyInfo.cs b/src/Build/Instance/ReflectableTaskPropertyInfo.cs
index 571ba866933..6518e901fdd 100644
--- a/src/Build/Instance/ReflectableTaskPropertyInfo.cs
+++ b/src/Build/Instance/ReflectableTaskPropertyInfo.cs
@@ -17,14 +17,19 @@ namespace Microsoft.Build.Execution
internal class ReflectableTaskPropertyInfo : TaskPropertyInfo
{
///
- /// The reflection-produced PropertyInfo.
+ /// The name of the generated tasks.
///
- private PropertyInfo _propertyInfo;
+ private readonly string taskName;
///
- /// The type of the generated tasks.
+ /// Function for accessing information about a property on a task via its name.
///
- private Type _taskType;
+ private readonly Func getProperty;
+
+ ///
+ /// The reflection-produced PropertyInfo.
+ ///
+ private PropertyInfo _propertyInfo;
///
/// Initializes a new instance of the class.
@@ -35,7 +40,16 @@ internal ReflectableTaskPropertyInfo(TaskPropertyInfo taskPropertyInfo, Type tas
: base(taskPropertyInfo.Name, taskPropertyInfo.PropertyType, taskPropertyInfo.Output, taskPropertyInfo.Required)
{
ErrorUtilities.VerifyThrowArgumentNull(taskType, nameof(taskType));
- _taskType = taskType;
+ getProperty = taskType.GetProperty;
+ taskName = taskType.FullName;
+ }
+
+ internal ReflectableTaskPropertyInfo(TaskPropertyInfo taskPropertyInfo, TypeInformation typeInformation)
+ : base(taskPropertyInfo.Name, taskPropertyInfo.PropertyType, taskPropertyInfo.Output, taskPropertyInfo.Required)
+ {
+ ErrorUtilities.VerifyThrowArgumentNull(typeInformation, nameof(typeInformation));
+ getProperty = typeInformation.GetProperty;
+ taskName = typeInformation.TypeName;
}
///
@@ -52,6 +66,15 @@ internal ReflectableTaskPropertyInfo(PropertyInfo propertyInfo)
_propertyInfo = propertyInfo;
}
+ internal ReflectableTaskPropertyInfo(TypeInformation.PropertyInfo propertyInfo) :
+ base(
+ propertyInfo.Name,
+ propertyInfo.PropertyType,
+ propertyInfo.OutputAttribute,
+ propertyInfo.RequiredAttribute)
+ {
+ }
+
///
/// Gets or sets the reflection-produced PropertyInfo.
///
@@ -61,8 +84,8 @@ internal PropertyInfo Reflection
{
if (_propertyInfo == null)
{
- _propertyInfo = _taskType.GetProperty(Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
- ErrorUtilities.VerifyThrow(_propertyInfo != null, "Could not find property {0} on type {1} that the task factory indicated should exist.", Name, _taskType.FullName);
+ _propertyInfo = getProperty(Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
+ ErrorUtilities.VerifyThrow(_propertyInfo != null, "Could not find property {0} on type {1} that the task factory indicated should exist.", Name, taskName);
}
return _propertyInfo;
diff --git a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs
index 97d721d4352..df336e05523 100644
--- a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs
+++ b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs
@@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
-
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
@@ -38,7 +38,7 @@ internal class AssemblyTaskFactory : ITaskFactory2
///
/// The loaded type (type, assembly name / file) of the task wrapped by the factory
///
- private LoadedType _loadedType;
+ private TypeInformation _typeInformation;
#if FEATURE_APPDOMAIN
///
@@ -84,18 +84,39 @@ public string FactoryName
{
get
{
- return _loadedType.Assembly.AssemblyLocation;
+ return _typeInformation.LoadInfo.AssemblyLocation;
}
}
///
/// Gets the type of task this factory creates.
+ /// This is only actually used in finding the TaskName immediately below this if LoadedType is not null.
+ /// The extra null checks are to avoid throwing, though it will if it cannot find the type.
///
public Type TaskType
{
- get { return _loadedType.Type; }
+ get { return _typeInformation.LoadedType?.Type ?? Type.GetType(_typeInformation.TypeName, true, true); }
}
+ ///
+ /// The name of the task.
+ ///
+ public string TaskName
+ {
+ get { return _typeInformation.LoadedType is null ? $"{_typeInformation.Namespace}.{_typeInformation.TypeName}" : TaskType.FullName; }
+ }
+
+ ///
+ /// All information known about a type. If it's loaded, that information mostly comes from the LoadedType object contained within.
+ /// If not, the information was collected in TypeLoader via System.Reflection.Metadata.
+ ///
+ public TypeInformation TypeInformation { get { return _typeInformation; } }
+
+ ///
+ /// Indicates whether this task implements IGeneratedTask. IGeneratedTask has useful methods for getting and setting properties.
+ ///
+ public bool ImplementsIGeneratedTask { get { return _typeInformation?.ImplementsIGeneratedTask ?? false; } }
+
///
/// Initializes this factory for instantiating tasks with a particular inline task block.
///
@@ -147,14 +168,9 @@ public bool Initialize(string taskName, IDictionary factoryIdent
///
public TaskPropertyInfo[] GetTaskParameters()
{
- PropertyInfo[] infos = _loadedType.Type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
- var propertyInfos = new TaskPropertyInfo[infos.Length];
- for (int i = 0; i < infos.Length; i++)
- {
- propertyInfos[i] = new ReflectableTaskPropertyInfo(infos[i]);
- }
-
- return propertyInfos;
+ return _typeInformation.LoadedType is null ?
+ _typeInformation.Properties.Select(prop => new ReflectableTaskPropertyInfo(prop)).ToArray() :
+ _typeInformation.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(prop => new ReflectableTaskPropertyInfo(prop)).ToArray();
}
///
@@ -250,13 +266,13 @@ public void CleanupTask(ITask task)
///
/// Initialize the factory from the task registry
///
- internal LoadedType InitializeFactory
+ internal TypeInformation InitializeFactory
(
AssemblyLoadInfo loadInfo,
string taskName,
IDictionary taskParameters,
string taskElementContents,
- IDictionary taskFactoryIdentityParameters,
+ ref Dictionary taskFactoryIdentityParameters,
bool taskHostFactoryExplicitlyRequested,
TargetLoggingContext targetLoggingContext,
ElementLocation elementLocation,
@@ -277,8 +293,31 @@ string taskProjectFile
{
ErrorUtilities.VerifyThrowArgumentLength(taskName, nameof(taskName));
_taskName = taskName;
- _loadedType = _typeLoader.Load(taskName, loadInfo);
- ProjectErrorUtilities.VerifyThrowInvalidProject(_loadedType != null, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, String.Empty);
+
+ // If the user requested a task host but provided us with an assembly name rather than an assembly file, pretend they didn't.
+ // Finding the path to the assembly file the runtime would load without actually loading the assembly would likely be a bug farm.
+ // Also, this should be a very unusual case.
+ _typeInformation = _typeLoader.Load(taskName, loadInfo, taskHostFactoryExplicitlyRequested && (loadInfo.AssemblyFile is not null || loadInfo.AssemblyName.StartsWith("Microsoft.Build")), out TaskRuntimeInformation runtimeInformation);
+ _taskHostFactoryExplicitlyRequested = runtimeInformation.TaskHostNeeded;
+ if (runtimeInformation.Architecture is not null)
+ {
+ taskFactoryIdentityParameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase);
+ taskFactoryIdentityParameters[XMakeAttributes.architecture] = runtimeInformation.Architecture;
+ _factoryIdentityParameters = taskFactoryIdentityParameters;
+ }
+ if (runtimeInformation.Runtime is not null)
+ {
+ taskFactoryIdentityParameters ??= new Dictionary(StringComparer.OrdinalIgnoreCase);
+ taskFactoryIdentityParameters[XMakeAttributes.runtime] = runtimeInformation.Runtime;
+ _factoryIdentityParameters = taskFactoryIdentityParameters;
+ }
+
+ // If the user specifically requests a code task factory, and the type wasn't already loaded, we need a way to verify that it really found a matching type. Properties is an array, so it should never be null,
+ // though it could be an empty array.
+ ProjectErrorUtilities.VerifyThrowInvalidProject(_typeInformation is not null && (_typeInformation.LoadedType != null || _typeInformation.Properties != null), elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, String.Empty);
+
+ _typeInformation.LoadInfo = loadInfo;
+ _typeInformation.TypeName ??= taskName;
}
catch (TargetInvocationException e)
{
@@ -309,7 +348,7 @@ string taskProjectFile
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message);
}
- return _loadedType;
+ return _typeInformation;
}
///
@@ -362,7 +401,7 @@ internal ITask CreateTaskInstance(ElementLocation taskLocation, TaskLoggingConte
mergedParameters[XMakeAttributes.architecture] = XMakeAttributes.GetCurrentMSBuildArchitecture();
}
- TaskHostTask task = new TaskHostTask(taskLocation, taskLoggingContext, buildComponentHost, mergedParameters, _loadedType
+ TaskHostTask task = new TaskHostTask(taskLocation, taskLoggingContext, buildComponentHost, mergedParameters, _typeInformation
#if FEATURE_APPDOMAIN
, appDomainSetup
#endif
@@ -371,17 +410,13 @@ internal ITask CreateTaskInstance(ElementLocation taskLocation, TaskLoggingConte
}
else
{
-#if FEATURE_APPDOMAIN
- AppDomain taskAppDomain = null;
-#endif
-
- ITask taskInstance = TaskLoader.CreateTask(_loadedType, _taskName, taskLocation.File, taskLocation.Line, taskLocation.Column, new TaskLoader.LogError(ErrorLoggingDelegate)
+ ITask taskInstance = TaskLoader.CreateTask(_typeInformation, _taskName, taskLocation.File, taskLocation.Line, taskLocation.Column, new TaskLoader.LogError(ErrorLoggingDelegate)
#if FEATURE_APPDOMAIN
, appDomainSetup
#endif
, isOutOfProc
#if FEATURE_APPDOMAIN
- , out taskAppDomain
+ , out AppDomain taskAppDomain
#endif
);
@@ -411,13 +446,13 @@ internal bool TaskNameCreatableByFactory(string taskName, IDictionary MergeTaskFactoryParameterSets(IDictio
if (!XMakeAttributes.TryMergeArchitectureValues(taskArchitecture, usingTaskArchitecture, out mergedArchitecture))
{
- ErrorUtilities.ThrowInternalError("How did we get two runtime values that were unmergeable?");
+ ErrorUtilities.ThrowInternalError("How did we get two architecture values that were unmergeable?");
}
else
{
diff --git a/src/Build/Instance/TaskFactories/TaskHostTask.cs b/src/Build/Instance/TaskFactories/TaskHostTask.cs
index ce29ccbed30..5851fe64c08 100644
--- a/src/Build/Instance/TaskFactories/TaskHostTask.cs
+++ b/src/Build/Instance/TaskFactories/TaskHostTask.cs
@@ -74,7 +74,7 @@ internal class TaskHostTask : IGeneratedTask, ICancelableTask, INodePacketFactor
///
/// The type of the task that we are wrapping.
///
- private LoadedType _taskType;
+ private TypeInformation _taskType;
#if FEATURE_APPDOMAIN
///
@@ -124,7 +124,7 @@ internal class TaskHostTask : IGeneratedTask, ICancelableTask, INodePacketFactor
///
/// Constructor
///
- public TaskHostTask(IElementLocation taskLocation, TaskLoggingContext taskLoggingContext, IBuildComponentHost buildComponentHost, IDictionary taskHostParameters, LoadedType taskType
+ public TaskHostTask(IElementLocation taskLocation, TaskLoggingContext taskLoggingContext, IBuildComponentHost buildComponentHost, IDictionary taskHostParameters, TypeInformation taskType
#if FEATURE_APPDOMAIN
, AppDomainSetup appDomainSetup
#endif
@@ -203,16 +203,28 @@ public object GetPropertyValue(TaskPropertyInfo property)
{
// If we returned an exception, then we want to throw it when we
// do the get.
- if (value is Exception)
+ if (value is Exception eVal)
{
- throw (Exception)value;
+ throw eVal;
}
return value;
}
+ else if (_taskType.LoadedType is null)
+ {
+ switch (property.Name)
+ {
+ case "HostObject":
+ return this.HostObject;
+ case "BuildEngine":
+ return this.BuildEngine;
+ default:
+ throw new InternalErrorException($"{property.Name} is not a property on TaskHostTask, or else it needs to be added to its registered list of properties.");
+ }
+ }
else
{
- PropertyInfo parameter = _taskType.Type.GetProperty(property.Name, BindingFlags.Instance | BindingFlags.Public);
+ PropertyInfo parameter = _taskType.GetProperty(property.Name, BindingFlags.Instance | BindingFlags.Public);
return parameter.GetValue(this, null);
}
}
@@ -244,7 +256,7 @@ public bool Execute()
// log that we are about to spawn the task host
string runtime = _taskHostParameters[XMakeAttributes.runtime];
string architecture = _taskHostParameters[XMakeAttributes.architecture];
- _taskLoggingContext.LogComment(MessageImportance.Low, "ExecutingTaskInTaskHost", _taskType.Type.Name, _taskType.Assembly.AssemblyLocation, runtime, architecture);
+ _taskLoggingContext.LogComment(MessageImportance.Low, "ExecutingTaskInTaskHost", _taskType.TypeName, _taskType.LoadInfo.AssemblyLocation ?? _taskType.LoadedType.LoadedAssembly.Location, runtime, architecture);
// set up the node
lock (_taskHostLock)
@@ -253,9 +265,7 @@ public bool Execute()
ErrorUtilities.VerifyThrowInternalNull(_taskHostProvider, "taskHostProvider");
}
- TaskHostConfiguration hostConfiguration =
- new TaskHostConfiguration
- (
+ TaskHostConfiguration hostConfiguration = new(
_buildComponentHost.BuildParameters.NodeId,
NativeMethodsShared.GetCurrentDirectory(),
CommunicationsUtilities.GetEnvironmentVariables(),
@@ -268,8 +278,8 @@ public bool Execute()
BuildEngine.ColumnNumberOfTaskNode,
BuildEngine.ProjectFileOfTaskNode,
BuildEngine.ContinueOnError,
- _taskType.Type.FullName,
- AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly),
+ _taskType.TypeName,
+ _taskType.Path,
_buildComponentHost.BuildParameters.LogTaskInputs,
_setParameters,
new Dictionary(_buildComponentHost.BuildParameters.GlobalProperties),
@@ -465,8 +475,8 @@ private void HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplet
}
else
{
- exceptionMessageArgs = new string[] { _taskType.Type.Name,
- AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly),
+ exceptionMessageArgs = new string[] { _taskType.TypeName,
+ _taskType.LoadInfo.AssemblyLocation ?? _taskType.LoadedType.LoadedAssembly.Location,
string.Empty };
}
@@ -558,11 +568,11 @@ private void LogErrorUnableToCreateTaskHost(HandshakeOptions requiredContext, st
if (e == null)
{
- _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostAcquireFailed", _taskType.Type.Name, runtime, architecture, msbuildLocation);
+ _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostAcquireFailed", _taskType.TypeName, runtime, architecture, msbuildLocation);
}
else
{
- _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostNodeFailedToLaunch", _taskType.Type.Name, runtime, architecture, msbuildLocation, e.ErrorCode, e.Message);
+ _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostNodeFailedToLaunch", _taskType.TypeName, runtime, architecture, msbuildLocation, e.ErrorCode, e.Message);
}
}
}
diff --git a/src/Build/Instance/TaskFactoryWrapper.cs b/src/Build/Instance/TaskFactoryWrapper.cs
index 72bf3ec5624..dea1f5c7cdb 100644
--- a/src/Build/Instance/TaskFactoryWrapper.cs
+++ b/src/Build/Instance/TaskFactoryWrapper.cs
@@ -7,6 +7,8 @@
using Microsoft.Build.Collections;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
+using Microsoft.Build.BackEnd;
+using System.Linq;
#nullable disable
@@ -62,13 +64,13 @@ internal sealed class TaskFactoryWrapper
///
/// Creates an instance of this class for the given type.
///
- internal TaskFactoryWrapper(ITaskFactory taskFactory, LoadedType taskFactoryLoadInfo, string taskName, IDictionary factoryIdentityParameters)
+ internal TaskFactoryWrapper(ITaskFactory taskFactory, TypeInformation taskFactoryLoadInfo, string taskName, IDictionary factoryIdentityParameters)
{
ErrorUtilities.VerifyThrowArgumentNull(taskFactory, nameof(taskFactory));
ErrorUtilities.VerifyThrowArgumentLength(taskName, nameof(taskName));
_taskFactory = taskFactory;
_taskName = taskName;
- TaskFactoryLoadedType = taskFactoryLoadInfo;
+ TaskFactoryTypeInformation = taskFactoryLoadInfo;
_factoryIdentityParameters = factoryIdentityParameters;
}
@@ -79,11 +81,7 @@ internal TaskFactoryWrapper(ITaskFactory taskFactory, LoadedType taskFactoryLoad
///
/// Load information about the task factory itself
///
- public LoadedType TaskFactoryLoadedType
- {
- get;
- private set;
- }
+ public TypeInformation TaskFactoryTypeInformation { get; private set; }
///
/// The task factory wrapped by the wrapper
@@ -187,15 +185,14 @@ internal void SetPropertyValue(ITask task, TaskPropertyInfo property, object val
ErrorUtilities.VerifyThrowArgumentNull(task, nameof(task));
ErrorUtilities.VerifyThrowArgumentNull(property, nameof(property));
- IGeneratedTask generatedTask = task as IGeneratedTask;
- if (generatedTask != null)
+ if (task is IGeneratedTask generatedTask)
{
generatedTask.SetPropertyValue(property, value);
}
else
{
- ReflectableTaskPropertyInfo propertyInfo = (ReflectableTaskPropertyInfo)property;
- propertyInfo.Reflection.SetValue(task, value, null);
+ PropertyInfo prop = task.GetType().GetProperty(property.Name);
+ prop.SetValue(task, value);
}
}
@@ -207,23 +204,23 @@ internal object GetPropertyValue(ITask task, TaskPropertyInfo property)
ErrorUtilities.VerifyThrowArgumentNull(task, nameof(task));
ErrorUtilities.VerifyThrowArgumentNull(property, nameof(property));
- IGeneratedTask generatedTask = task as IGeneratedTask;
- if (generatedTask != null)
+ if (task is IGeneratedTask generatedTask)
{
return generatedTask.GetPropertyValue(property);
}
else
{
- ReflectableTaskPropertyInfo propertyInfo = property as ReflectableTaskPropertyInfo;
- if (propertyInfo != null)
- {
- return propertyInfo.Reflection.GetValue(task, null);
- }
- else
+ if (property is ReflectableTaskPropertyInfo propertyInfo)
{
- ErrorUtilities.ThrowInternalError("Task does not implement IGeneratedTask and we don't have {0} either.", typeof(ReflectableTaskPropertyInfo).Name);
- throw new InternalErrorException(); // unreachable
+ try
+ {
+ return propertyInfo.Reflection.GetValue(task, null);
+ }
+ // If the type was not loaded, we may end up with a NotImplementedException. Ignore it.
+ catch (NotImplementedException) { }
}
+
+ return task.GetType().GetTypeInfo().GetProperty(property.Name);
}
}
@@ -246,7 +243,9 @@ private void PopulatePropertyInfoCacheIfNecessary()
{
if (_propertyInfoCache == null)
{
- bool taskTypeImplementsIGeneratedTask = typeof(IGeneratedTask).IsAssignableFrom(_taskFactory.TaskType);
+ bool taskTypeImplementsIGeneratedTask = _taskFactory is AssemblyTaskFactory assemblyTaskFactory ?
+ assemblyTaskFactory.ImplementsIGeneratedTask :
+ typeof(IGeneratedTask).IsAssignableFrom(_taskFactory.TaskType);
TaskPropertyInfo[] propertyInfos = _taskFactory.GetTaskParameters();
for (int i = 0; i < propertyInfos.Length; i++)
@@ -257,7 +256,9 @@ private void PopulatePropertyInfoCacheIfNecessary()
TaskPropertyInfo propertyInfo = propertyInfos[i];
if (!taskTypeImplementsIGeneratedTask)
{
- propertyInfo = new ReflectableTaskPropertyInfo(propertyInfo, _taskFactory.TaskType);
+ propertyInfo = _taskFactory is AssemblyTaskFactory assemblyTaskFactory2 ?
+ new ReflectableTaskPropertyInfo(propertyInfo, assemblyTaskFactory2.TypeInformation) :
+ new ReflectableTaskPropertyInfo(propertyInfo, _taskFactory.TaskType);
}
try
diff --git a/src/Build/Instance/TaskRegistry.cs b/src/Build/Instance/TaskRegistry.cs
index 390f8e29f92..53e2516bd53 100644
--- a/src/Build/Instance/TaskRegistry.cs
+++ b/src/Build/Instance/TaskRegistry.cs
@@ -436,7 +436,7 @@ ElementLocation elementLocation
targetLoggingContext.LogComment(MessageImportance.Low, "TaskFoundFromFactory", taskName, taskFactory.Name);
}
- if (taskFactory.TaskFactoryLoadedType.HasSTAThreadAttribute())
+ if (taskFactory.TaskFactoryTypeInformation.HasSTAThreadAttribute)
{
targetLoggingContext.LogComment(MessageImportance.Low, "TaskNeedsSTA", taskName);
}
@@ -754,6 +754,7 @@ public string Name
public IDictionary TaskIdentityParameters
{
get { return _taskIdentityParameters; }
+ internal set { _taskIdentityParameters = value; }
}
///
@@ -1284,7 +1285,7 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
AssemblyLoadInfo taskFactoryLoadInfo = TaskFactoryAssemblyLoadInfo;
ErrorUtilities.VerifyThrow(taskFactoryLoadInfo != null, "TaskFactoryLoadInfo should never be null");
ITaskFactory factory = null;
- LoadedType loadedType = null;
+ TypeInformation typeInformation = null;
bool isAssemblyTaskFactory = String.Equals(TaskFactoryAttributeName, AssemblyTaskFactory, StringComparison.OrdinalIgnoreCase);
bool isTaskHostFactory = String.Equals(TaskFactoryAttributeName, TaskHostFactory, StringComparison.OrdinalIgnoreCase);
@@ -1300,8 +1301,9 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
);
// Create an instance of the internal assembly task factory, it has the error handling built into its methods.
- AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
- loadedType = taskFactory.InitializeFactory(taskFactoryLoadInfo, RegisteredName, ParameterGroupAndTaskBody.UsingTaskParameters, ParameterGroupAndTaskBody.InlineTaskXmlBody, TaskFactoryParameters, explicitlyLaunchTaskHost, targetLoggingContext, elementLocation, taskProjectFile);
+ AssemblyTaskFactory taskFactory = new();
+ typeInformation = taskFactory.InitializeFactory(taskFactoryLoadInfo, RegisteredName, ParameterGroupAndTaskBody.UsingTaskParameters, ParameterGroupAndTaskBody.InlineTaskXmlBody, ref _taskFactoryParameters, explicitlyLaunchTaskHost, targetLoggingContext, elementLocation, taskProjectFile);
+ _taskIdentity.TaskIdentityParameters = _taskFactoryParameters;
factory = taskFactory;
}
else
@@ -1327,9 +1329,9 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
}
// Make sure we only look for task factory classes when loading based on the name
- loadedType = s_taskFactoryTypeLoader.Load(TaskFactoryAttributeName, taskFactoryLoadInfo);
+ typeInformation = s_taskFactoryTypeLoader.Load(TaskFactoryAttributeName, taskFactoryLoadInfo, false, out _);
- if (loadedType == null)
+ if (typeInformation == null)
{
// We could not find the type (this is what null means from the Load method) but there is no reason given so we can only log the fact that
// we could not find the name given in the task factory attribute in the class specified in the assembly File or assemblyName fields.
@@ -1367,9 +1369,9 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
// We have loaded the type, lets now try and construct it
// Any exceptions from the constructor of the task factory will be caught lower down and turned into an InvalidProjectFileExceptions
#if FEATURE_APPDOMAIN
- factory = (ITaskFactory)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(loadedType.Type.GetTypeInfo().Assembly.FullName, loadedType.Type.FullName);
+ factory = (ITaskFactory)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(typeInformation.LoadInfo.AssemblyName ?? typeInformation.LoadedType.Type.GetTypeInfo().Assembly.FullName, typeInformation.TypeName);
#else
- factory = (ITaskFactory) Activator.CreateInstance(loadedType.Type);
+ factory = (ITaskFactory)Activator.CreateInstance(typeInformation.LoadInfo.AssemblyName ?? typeInformation.LoadedType.LoadedAssembly.FullName, typeInformation.TypeName)?.Unwrap();
#endif
TaskFactoryLoggingHost taskFactoryLoggingHost = new TaskFactoryLoggingHost(true /*I dont have the data at this point, the safest thing to do is make sure events are serializable*/, elementLocation, targetLoggingContext);
@@ -1388,15 +1390,14 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
// TaskFactoryParameters will always be null unless specifically created to have runtime and architecture parameters.
if (TaskFactoryParameters != null)
{
- targetLoggingContext.LogWarning
- (
+ targetLoggingContext.LogWarning(
null,
- new BuildEventFileInfo(elementLocation),
- "TaskFactoryWillIgnoreTaskFactoryParameters",
- factory.FactoryName,
- XMakeAttributes.runtime,
- XMakeAttributes.architecture,
- RegisteredName);
+ new BuildEventFileInfo(elementLocation),
+ "TaskFactoryWillIgnoreTaskFactoryParameters",
+ factory.FactoryName,
+ XMakeAttributes.runtime,
+ XMakeAttributes.architecture,
+ RegisteredName);
}
}
@@ -1460,7 +1461,7 @@ private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLo
}
}
- _taskFactoryWrapperInstance = new TaskFactoryWrapper(factory, loadedType, RegisteredName, TaskFactoryParameters);
+ _taskFactoryWrapperInstance = new TaskFactoryWrapper(factory, typeInformation, RegisteredName, TaskFactoryParameters);
}
return true;
diff --git a/src/Build/Logging/LoggerDescription.cs b/src/Build/Logging/LoggerDescription.cs
index dc7950123bb..d31a93b66b7 100644
--- a/src/Build/Logging/LoggerDescription.cs
+++ b/src/Build/Logging/LoggerDescription.cs
@@ -202,7 +202,7 @@ private ILogger CreateLogger(bool forwardingLogger)
if (forwardingLogger)
{
// load the logger from its assembly
- LoadedType loggerClass = (new TypeLoader(s_forwardingLoggerClassFilter)).Load(_loggerClassName, _loggerAssembly);
+ LoadedType loggerClass = (new TypeLoader(s_forwardingLoggerClassFilter)).Load(_loggerClassName, _loggerAssembly, false, out _).LoadedType;
if (loggerClass != null)
{
@@ -213,7 +213,7 @@ private ILogger CreateLogger(bool forwardingLogger)
else
{
// load the logger from its assembly
- LoadedType loggerClass = (new TypeLoader(s_loggerClassFilter)).Load(_loggerClassName, _loggerAssembly);
+ LoadedType loggerClass = (new TypeLoader(s_loggerClassFilter)).Load(_loggerClassName, _loggerAssembly, false, out _).LoadedType;
if (loggerClass != null)
{
diff --git a/src/Build/Microsoft.Build.csproj b/src/Build/Microsoft.Build.csproj
index cd99bc84721..b05dc8c9617 100644
--- a/src/Build/Microsoft.Build.csproj
+++ b/src/Build/Microsoft.Build.csproj
@@ -35,7 +35,7 @@
-
+
@@ -47,7 +47,6 @@
-
@@ -717,6 +716,10 @@
SharedUtilities\LoadedType.cs
true
+
+ SharedUtilities\TypeInformation.cs
+ true
+
InprocTrackingNativeMethods.cs
true
diff --git a/src/MSBuild/MSBuild.csproj b/src/MSBuild/MSBuild.csproj
index 803083dd1fc..82122c476ea 100644
--- a/src/MSBuild/MSBuild.csproj
+++ b/src/MSBuild/MSBuild.csproj
@@ -135,8 +135,9 @@
+
- true
+ true
true
diff --git a/src/MSBuild/OutOfProcTaskAppDomainWrapperBase.cs b/src/MSBuild/OutOfProcTaskAppDomainWrapperBase.cs
index 8405d0474a0..bbc70028128 100644
--- a/src/MSBuild/OutOfProcTaskAppDomainWrapperBase.cs
+++ b/src/MSBuild/OutOfProcTaskAppDomainWrapperBase.cs
@@ -10,6 +10,7 @@
using Microsoft.Build.BackEnd;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
+using System.IO;
#if FEATURE_APPDOMAIN
using System.Runtime.Remoting;
#endif
@@ -113,11 +114,11 @@ IDictionary taskParams
#endif
wrappedTask = null;
- LoadedType taskType = null;
+ TypeInformation taskType = null;
try
{
TypeLoader typeLoader = new TypeLoader(TaskLoader.IsTaskClass);
- taskType = typeLoader.Load(taskName, AssemblyLoadInfo.Create(null, taskLocation));
+ taskType = typeLoader.Load(taskName, AssemblyLoadInfo.Create(null, taskLocation), false, out _);
}
catch (Exception e) when (!ExceptionHandling.IsCriticalException(e))
{
@@ -135,10 +136,10 @@ IDictionary taskParams
}
OutOfProcTaskHostTaskResult taskResult;
- if (taskType.HasSTAThreadAttribute())
+ if (taskType.HasSTAThreadAttribute)
{
#if FEATURE_APARTMENT_STATE
- taskResult = InstantiateAndExecuteTaskInSTAThread(oopTaskHostNode, taskType, taskName, taskLocation, taskFile, taskLine, taskColumn,
+ taskResult = InstantiateAndExecuteTaskInSTAThread(oopTaskHostNode, taskType.LoadedType, taskName, taskLocation, taskFile, taskLine, taskColumn,
#if FEATURE_APPDOMAIN
appDomainSetup,
#endif
@@ -155,7 +156,7 @@ IDictionary taskParams
}
else
{
- taskResult = InstantiateAndExecuteTask(oopTaskHostNode, taskType, taskName, taskLocation, taskFile, taskLine, taskColumn,
+ taskResult = InstantiateAndExecuteTask(oopTaskHostNode, taskType.LoadedType, taskName, taskLocation, taskFile, taskLine, taskColumn,
#if FEATURE_APPDOMAIN
appDomainSetup,
#endif
@@ -296,7 +297,7 @@ IDictionary taskParams
try
{
- wrappedTask = TaskLoader.CreateTask(taskType, taskName, taskFile, taskLine, taskColumn, new TaskLoader.LogError(LogErrorDelegate),
+ wrappedTask = TaskLoader.CreateTask(new TypeInformation(taskType), taskName, taskFile, taskLine, taskColumn, new TaskLoader.LogError(LogErrorDelegate),
#if FEATURE_APPDOMAIN
appDomainSetup,
#endif
diff --git a/src/MSBuild/OutOfProcTaskHostNode.cs b/src/MSBuild/OutOfProcTaskHostNode.cs
index 6b54a4ec089..a5d72babc54 100644
--- a/src/MSBuild/OutOfProcTaskHostNode.cs
+++ b/src/MSBuild/OutOfProcTaskHostNode.cs
@@ -895,7 +895,7 @@ private void RunTask(object state)
taskResult = _taskWrapper.ExecuteTask
(
- this as IBuildEngine,
+ this,
taskName,
taskLocation,
taskConfiguration.ProjectFileOfTask,
diff --git a/src/MSBuildTaskHost/MSBuildTaskHost.csproj b/src/MSBuildTaskHost/MSBuildTaskHost.csproj
index f56435ec284..9a454bde581 100644
--- a/src/MSBuildTaskHost/MSBuildTaskHost.csproj
+++ b/src/MSBuildTaskHost/MSBuildTaskHost.csproj
@@ -176,7 +176,8 @@
-
+
+
diff --git a/src/MSBuildTaskHost/TypeLoader.cs b/src/MSBuildTaskHost/TypeLoader.cs
index 5b4833472c4..b03e1d6c0cf 100644
--- a/src/MSBuildTaskHost/TypeLoader.cs
+++ b/src/MSBuildTaskHost/TypeLoader.cs
@@ -127,12 +127,15 @@ internal static bool IsPartialTypeNameMatch(string typeName1, string typeName2)
/// any) is unambiguous; otherwise, if there are multiple types with the same name in different namespaces, the first type
/// found will be returned.
///
- internal LoadedType Load
+ internal TypeInformation Load
(
string typeName,
- AssemblyLoadInfo assembly
+ AssemblyLoadInfo assembly,
+ bool taskHostFactoryExplicitlyRequested,
+ out bool taskHostFactoryNeeded
)
{
+ taskHostFactoryNeeded = false;
return GetLoadedType(s_cacheOfLoadedTypesByFilter, typeName, assembly);
}
@@ -148,7 +151,7 @@ internal LoadedType ReflectionOnlyLoad
AssemblyLoadInfo assembly
)
{
- return GetLoadedType(s_cacheOfReflectionOnlyLoadedTypesByFilter, typeName, assembly);
+ return GetLoadedType(s_cacheOfReflectionOnlyLoadedTypesByFilter, typeName, assembly).LoadedType;
}
///
@@ -156,7 +159,7 @@ AssemblyLoadInfo assembly
/// any) is unambiguous; otherwise, if there are multiple types with the same name in different namespaces, the first type
/// found will be returned.
///
- private LoadedType GetLoadedType(Concurrent.ConcurrentDictionary> cache, string typeName, AssemblyLoadInfo assembly)
+ private TypeInformation GetLoadedType(Concurrent.ConcurrentDictionary> cache, string typeName, AssemblyLoadInfo assembly)
{
// A given type filter have been used on a number of assemblies, Based on the type filter we will get another dictionary which
// will map a specific AssemblyLoadInfo to a AssemblyInfoToLoadedTypes class which knows how to find a typeName in a given assembly.
@@ -233,12 +236,11 @@ internal AssemblyInfoToLoadedTypes(TypeFilter typeFilter, AssemblyLoadInfo loadI
///
/// Determine if a given type name is in the assembly or not. Return null if the type is not in the assembly
///
- internal LoadedType GetLoadedTypeByTypeName(string typeName)
+ internal TypeInformation GetLoadedTypeByTypeName(string typeName)
{
ErrorUtilities.VerifyThrowArgumentNull(typeName, nameof(typeName));
// Only one thread should be doing operations on this instance of the object at a time.
-
Type type = _typeNameToType.GetOrAdd(typeName, (key) =>
{
if ((_assemblyLoadInfo.AssemblyName != null) && (typeName.Length > 0))
@@ -284,7 +286,7 @@ internal LoadedType GetLoadedTypeByTypeName(string typeName)
return null;
});
- return type != null ? new LoadedType(type, _assemblyLoadInfo, _loadedAssembly) : null;
+ return type != null ? new TypeInformation(new LoadedType(type, _assemblyLoadInfo, _loadedAssembly)) : null;
}
///
diff --git a/src/Shared/AssemblyLoadInfo.cs b/src/Shared/AssemblyLoadInfo.cs
index 271a077efaa..0400d847b4e 100644
--- a/src/Shared/AssemblyLoadInfo.cs
+++ b/src/Shared/AssemblyLoadInfo.cs
@@ -176,7 +176,7 @@ private sealed class AssemblyLoadInfoWithFile : AssemblyLoadInfo
///
internal AssemblyLoadInfoWithFile(string assemblyFile)
{
- ErrorUtilities.VerifyThrow(Path.IsPathRooted(assemblyFile), "Assembly file path should be rooted");
+ ErrorUtilities.VerifyThrow(Path.IsPathRooted(assemblyFile), $"Assembly file path should be rooted: {assemblyFile}");
_assemblyFile = assemblyFile;
}
diff --git a/src/Shared/LoadedType.cs b/src/Shared/LoadedType.cs
index eeae7eb79ab..cd29aacc43e 100644
--- a/src/Shared/LoadedType.cs
+++ b/src/Shared/LoadedType.cs
@@ -92,7 +92,7 @@ private void CheckForHardcodedSTARequirement()
{
AssemblyName assemblyName = _type.GetTypeInfo().Assembly.GetName();
Version lastVersionToForce = new Version(3, 5);
- if (assemblyName.Version.CompareTo(lastVersionToForce) > 0)
+ if (assemblyName.Version > lastVersionToForce)
{
if (String.Equals(assemblyName.Name, "PresentationBuildTasks", StringComparison.OrdinalIgnoreCase))
{
diff --git a/src/Shared/Resources/Strings.shared.resx b/src/Shared/Resources/Strings.shared.resx
index 4a2ab0dd185..71d77481bbc 100644
--- a/src/Shared/Resources/Strings.shared.resx
+++ b/src/Shared/Resources/Strings.shared.resx
@@ -278,10 +278,18 @@
MSB5028: Solution filter file at "{0}" includes project "{1}" that is not in the solution file at "{2}".
{StrBegin="MSB5028: "}UE: The project filename is provided separately to loggers.
+
+ MSB5029: The '{0}' task was built for {1}, but MSBuild in use targets {2}. MSBuild does not support building tasks across frameworks.
+ {StrBegin="MSB5029: "}
+
+
+ MSB5030: .NET Core MSBuild does not support 32-bit tasks.
+ {StrBegin="MSB5030: "}
+