public EvaluationContext (string source, ExpressionEvaluator evaluator) { Source = source; Evaluator = evaluator; }
bool RunBuildTask (ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; var host = request.HostServices == null ? null : request.HostServices.GetHostObject (request.ProjectFullPath, target.Name, taskInstance.Name); // Create Task instance. var factoryIdentityParameters = new Dictionary<string,string> (); #if NET_4_5 factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime; factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture; #endif var task = args.BuildTaskFactory.CreateTask (taskInstance.Name, factoryIdentityParameters, this); if (task == null) throw new InvalidOperationException (string.Format ("TaskFactory {0} returned null Task", args.BuildTaskFactory)); LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using task {0} from {1}", taskInstance.Name, task.GetType ()), null, null, MessageImportance.Low)); task.HostObject = host; task.BuildEngine = this; // Prepare task parameters. var evaluator = new ExpressionEvaluator (project); var evaluatedTaskParams = taskInstance.Parameters.Select (p => new KeyValuePair<string,string> (p.Key, project.ExpandString (evaluator, p.Value))); var requiredProps = task.GetType ().GetProperties () .Where (p => p.CanWrite && p.GetCustomAttributes (typeof (RequiredAttribute), true).Any ()); var missings = requiredProps.Where (p => !evaluatedTaskParams.Any (tp => tp.Key.Equals (p.Name, StringComparison.OrdinalIgnoreCase))); if (missings.Any ()) throw new InvalidOperationException (string.Format ("Task {0} of type {1} is used without specifying mandatory property: {2}", taskInstance.Name, task.GetType (), string.Join (", ", missings.Select (p => p.Name).ToArray ()))); foreach (var p in evaluatedTaskParams) { switch (p.Key.ToLower ()) { case "condition": case "continueonerror": continue; } var prop = task.GetType ().GetProperty (p.Key); if (prop == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1}", taskInstance.Name, p.Key)); if (!prop.CanWrite) throw new InvalidOperationException (string.Format ("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key)); if (string.IsNullOrEmpty (p.Value) && !requiredProps.Contains (prop)) continue; try { prop.SetValue (task, ConvertTo (p.Value, prop.PropertyType, evaluator), null); } catch (Exception ex) { throw new InvalidOperationException (string.Format ("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex); } } // Do execute task. bool taskSuccess = false; event_source.FireTaskStarted (this, new TaskStartedEventArgs ("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name)); try { taskSuccess = task.Execute (); if (!taskSuccess) { targetResult.Failure (null); if (!ContinueOnError) { return false; } } else { // Evaluate task output properties and items. foreach (var to in taskInstance.Outputs) { if (!project.EvaluateCondition (to.Condition)) continue; var toItem = to as ProjectTaskOutputItemInstance; var toProp = to as ProjectTaskOutputPropertyInstance; string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter; var pi = task.GetType ().GetProperty (taskParameter); if (pi == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter)); if (!pi.CanRead) throw new InvalidOperationException (string.Format ("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter)); var value = pi.GetValue (task, null); var valueString = ConvertFrom (value); if (toItem != null) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, valueString), null, null, MessageImportance.Low)); Action<ITaskItem> addItem = i => { var metadata = new ArrayList (i.MetadataNames).ToArray ().Cast<string> ().Select (n => new KeyValuePair<string,string> (n, i.GetMetadata (n))); args.Project.AddItem (toItem.ItemType, i.ItemSpec, metadata); }; var taskItemArray = value as ITaskItem []; if (taskItemArray != null) { foreach (var ti in taskItemArray) addItem (ti); } else { var taskItem = value as ITaskItem; if (taskItem != null) addItem (taskItem); else foreach (var item in valueString.Split (';')) args.Project.AddItem (toItem.ItemType, item); } } else { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, valueString), null, null, MessageImportance.Low)); args.Project.SetProperty (toProp.PropertyName, valueString); } } } } finally { event_source.FireTaskFinished (this, new TaskFinishedEventArgs ("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess)); } return true; }
object ConvertTo (string source, Type targetType, ExpressionEvaluator evaluator) { if (targetType == typeof (ITaskItem) || targetType.IsSubclassOf (typeof (ITaskItem))) { var item = evaluator.EvaluatedTaskItems.FirstOrDefault (i => string.Equals (i.ItemSpec, source.Trim (), StringComparison.OrdinalIgnoreCase)); var ret = new TargetOutputTaskItem () { ItemSpec = source.Trim () }; if (item != null) foreach (string name in item.MetadataNames) ret.SetMetadata (name, item.GetMetadata (name)); return ret; } if (targetType.IsArray) return new ArrayList (source.Split (';').Select (s => s.Trim ()).Where (s => !string.IsNullOrEmpty (s)).Select (s => ConvertTo (s, targetType.GetElementType (), evaluator)).ToArray ()) .ToArray (targetType.GetElementType ()); if (targetType == typeof (bool)) { switch (source != null ? source.ToLower (CultureInfo.InvariantCulture) : string.Empty) { case "true": case "yes": case "on": return true; case "false": case "no": case "off": case "": return false; } } return Convert.ChangeType (source == "" ? null : source, targetType); }
public EvaluationContext(string source, ExpressionEvaluator evaluator) { Source = source; Evaluator = evaluator; }