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: "} +