public void BasicProxying()
        {          
            BuildItemGroup ig = new BuildItemGroup();
            BuildItem i1 = new BuildItem("name1", "value1");
            i1.SetMetadata("myMetaName", "myMetaValue");
            BuildItem i2 = new BuildItem("name2", "value2");
            ig.AddItem(i1);
            ig.AddItem(i2);

            BuildItemGroupProxy proxy = new BuildItemGroupProxy(ig);

            // Gather everything into our own table
            Hashtable list = new Hashtable(StringComparer.OrdinalIgnoreCase);
            foreach (DictionaryEntry item in proxy)
            {
                list.Add(item.Key, item.Value);
            }

            // Check we got all the items
            Assertion.AssertEquals(2, list.Count);
            Assertion.AssertEquals("value1", ((TaskItem)list["name1"]).ItemSpec);
            Assertion.AssertEquals("value2", ((TaskItem)list["name2"]).ItemSpec);

            // Check they have all their metadata
            int builtInMetadata = FileUtilities.ItemSpecModifiers.All.Length;
            Assertion.AssertEquals(1 + builtInMetadata, ((TaskItem)list["name1"]).MetadataCount);
            Assertion.AssertEquals(0 + builtInMetadata, ((TaskItem)list["name2"]).MetadataCount);
            Assertion.AssertEquals("myMetaValue", ((TaskItem)list["name1"]).GetMetadata("myMetaName"));
        }
        public void CantModifyThroughEnumerator()
        {
            BuildItemGroup ig = new BuildItemGroup();
            BuildItem i1 = new BuildItem("name1", "value1");
            i1.SetMetadata("myMetaName", "myMetaValue");
            ig.AddItem(i1);

            BuildItemGroupProxy proxy = new BuildItemGroupProxy(ig);

            Hashtable list = new Hashtable(StringComparer.OrdinalIgnoreCase);
            foreach (DictionaryEntry item in proxy)
            {
                list.Add(item.Key, item.Value);
            }

            // Change the item
            Assertion.AssertEquals("value1", ((TaskItem)list["name1"]).ItemSpec);
            ((TaskItem)list["name1"]).ItemSpec = "newItemSpec";
            ((TaskItem)list["name1"]).SetMetadata("newMetadata", "newMetadataValue");

            // We did change our copy
            Assertion.AssertEquals("newItemSpec", ((TaskItem)list["name1"]).ItemSpec);
            Assertion.AssertEquals("newMetadataValue", ((TaskItem)list["name1"]).GetMetadata("newMetadata"));
            Assertion.AssertEquals("myMetaValue", ((TaskItem)list["name1"]).GetMetadata("myMetaName"));

            // But get the item again
            list = new Hashtable(StringComparer.OrdinalIgnoreCase);
            foreach (DictionaryEntry item in proxy)
            {
                list.Add(item.Key, item.Value);
            }

            // Item value and metadata hasn't changed
            Assertion.AssertEquals("value1", ((TaskItem)list["name1"]).ItemSpec);
            Assertion.AssertEquals("", ((TaskItem)list["name1"]).GetMetadata("newMetadata"));
            Assertion.AssertEquals("myMetaValue", ((TaskItem)list["name1"]).GetMetadata("myMetaName"));
        }
示例#3
0
文件: Project.cs 项目: nikson/msbuild
        private ProjectBuildState InitializeForBuildingTargets(BuildRequest buildRequest)
        {
            ProjectBuildState buildContext = null;

            string[] targetNamesToBuild = buildRequest.TargetNames;
            
            // Initialize to the parent requests project context id
            int projectContextId = buildRequest.ParentBuildEventContext.ProjectContextId;

            BuildEventContext buildEventContext = null;

            // Determine if a project started event is required to be fired, if so we may need a new projectContextId
             if (buildRequest.FireProjectStartedFinishedEvents)
             {
                 //If we have not already used the context from the project yet, lets use that as our first event context
                 if (!haveUsedInitialProjectContextId)
                 {
                     buildEventContext = projectBuildEventContext;
                     haveUsedInitialProjectContextId = true;
                 }
                 else // We are going to need a new Project context Id and a new buildEventContext
                 {
                     projectContextId = parentEngine.GetNextProjectId();
                 }
             }

             if (buildEventContext == null)
             {
                 buildEventContext = new BuildEventContext
                                   (
                                       projectBuildEventContext.NodeId,
                                       projectBuildEventContext.TargetId,
                                       projectContextId,
                                       projectBuildEventContext.TaskId
                                    );
             }

            bool exitedDueToError = true;

            try
            {
                // Refreshing (reevaluating) a project may end up calling ResetBuildStatus which will mark
                // IsReset=true.  This is legitimate because when a project is being reevaluated, we want
                // to be explicit in saying that any targets that had run previously are no longer valid,
                // and we must rebuild them on the next build.
                this.RefreshProjectIfDirty();

                // Only log the project started event after making sure the project is reevaluated if necessary,
                // otherwise we could log stale item/property information.
                if (!ParentEngine.LoggingServices.OnlyLogCriticalEvents && buildRequest.FireProjectStartedFinishedEvents)
                {  
                    string joinedTargetNamesToBuild = null;
                    if (targetNamesToBuild != null && targetNamesToBuild.Length > 0)
                    {
                        joinedTargetNamesToBuild = EscapingUtilities.UnescapeAll(String.Join(";", targetNamesToBuild));
                    }

                    // Flag the start of the project build.
                    //
                    // This also passes all the current properties/items and their values. The logger might want to use the
                    // object it gets from this event to see updated property/item values later in the build: so be 
                    // careful to use the original "evaluatedProperties" and "evaluatedItems" table, not the clone 
                    // "EvaluatedProperties" or "EvaluatedItems" table. It's fine to pass these live tables, because we're 
                    // wrapping them in read-only proxies.
                    BuildPropertyGroup propertyGroupForStartedEvent = this.evaluatedProperties;

                    // If we are on the child process we need to fiure out which properties we need to serialize
                    if (ParentEngine.Router.ChildMode)
                    {
                        // Initially set it to empty so that we do not serialize all properties if we are on a child node
                        propertyGroupForStartedEvent = new BuildPropertyGroup();

                        // Get the list of properties to serialize to the parent node
                        string[] propertyListToSerialize = parentEngine.PropertyListToSerialize;
                        if (propertyListToSerialize != null && propertyListToSerialize.Length > 0)
                        {
                            foreach (string propertyToGet in propertyListToSerialize)
                            {
                                BuildProperty property = this.evaluatedProperties[propertyToGet];

                                //property can be null if propertyToGet does not exist
                                if (property != null)
                                {
                                    propertyGroupForStartedEvent.SetProperty(property);
                                }
                            }
                        }
                    }

                    BuildPropertyGroupProxy propertiesProxy = new BuildPropertyGroupProxy(propertyGroupForStartedEvent);
                    BuildItemGroupProxy itemsProxy = new BuildItemGroupProxy(this.evaluatedItems);

                    ParentEngine.LoggingServices.LogProjectStarted(this.projectId, buildRequest.ParentBuildEventContext, buildEventContext, FullFileName, joinedTargetNamesToBuild, propertiesProxy, itemsProxy);
                    
                    // See comment on DefaultToolsVersion setter.
                    if (treatinghigherToolsVersionsAs40)
                    {
                        ParentEngine.LoggingServices.LogComment(buildEventContext, MessageImportance.High, "TreatingHigherToolsVersionAs40", DefaultToolsVersion);
                    }

                    ParentEngine.LoggingServices.LogComment(buildEventContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", ToolsVersion);
                }

                // Incrementing the building count. A single project may be building more than once at a time
                // because of callbacks by the MSBuild task.
                this.buildingCount++;

                // Because we are about to build some targets, we are no longer going to be in the "reset"
                // state.
                this.IsReset = false;

                // This is an ArrayList of strings, where each string is the name of a target that
                // we need to build.  We start out by populating it with the list of targets specified
                // in the "InitialTargets" attribute of the <Project> node.
                ArrayList completeListOfTargetNamesToBuild = this.CombinedInitialTargetNames;

                if (buildRequest.UseResultsCache)
                {
                    buildRequest.InitialTargets = string.Join(";", (string[])completeListOfTargetNamesToBuild.ToArray(typeof(string)));
                    buildRequest.DefaultTargets = (this.DefaultBuildTargets != null) ? string.Join(";", this.DefaultBuildTargets) : string.Empty;
                    buildRequest.ProjectId = this.projectId;
                }

                // If no targets were passed in, use the "defaultTargets" from the
                // project file.
                if ((targetNamesToBuild == null) || (targetNamesToBuild.Length == 0))
                {
                    string[] defaultTargetsToBuild = this.DefaultBuildTargets;

                    // There wasn't at least one target in the project, then we have
                    // a problem.
                    ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(defaultTargetsToBuild != null,
                        new BuildEventFileInfo(this.FullFileName), "NoTargetSpecified");

                    completeListOfTargetNamesToBuild.AddRange(defaultTargetsToBuild);
                }
                else
                {
                    completeListOfTargetNamesToBuild.AddRange(targetNamesToBuild);
                }

                // Check if the client requests that the project should be unloaded once it is completed
                needToUnloadProject = buildRequest.UnloadProjectsOnCompletion || needToUnloadProject;
                buildContext = new ProjectBuildState(buildRequest, completeListOfTargetNamesToBuild, buildEventContext);
                exitedDueToError = false;
            }
            catch (InvalidProjectFileException e)
            {
                // Make sure the Invalid Project error gets logged *before* ProjectFinished.  Otherwise,
                // the log is confusing.
                this.ParentEngine.LoggingServices.LogInvalidProjectFileError(buildEventContext, e);
                // Mark the build request as completed and failed. The build context is either not created
                // or discarded
                buildRequest.BuildCompleted = true;
                buildRequest.BuildSucceeded = false;
                buildContext = null;
            }
            finally
            {
                if (exitedDueToError)
                {
                    this.buildingCount--;

                    if (buildRequest.FireProjectStartedFinishedEvents)
                    {
                        ParentEngine.LoggingServices.LogProjectFinished(
                            buildEventContext,
                            FullFileName,
                            false);
                    }
                }
            }
            return buildContext;
        }