2 // Project.cs: Project class
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Collections.Specialized;
37 using System.Xml.Schema;
38 using Microsoft.Build.Framework;
39 using Mono.XBuild.Framework;
41 namespace Microsoft.Build.BuildEngine {
42 public class Project {
45 Dictionary <string, List <string>> conditionedProperties;
46 string[] defaultTargets;
48 BuildItemGroup evaluatedItems;
49 BuildItemGroup evaluatedItemsIgnoringCondition;
50 Dictionary <string, BuildItemGroup> evaluatedItemsByName;
51 Dictionary <string, BuildItemGroup> evaluatedItemsByNameIgnoringCondition;
52 BuildPropertyGroup evaluatedProperties;
53 string firstTargetName;
55 BuildPropertyGroup globalProperties;
56 GroupingCollection groupingCollection;
59 BuildItemGroupCollection itemGroups;
60 ImportCollection imports;
61 string initialTargets;
62 bool needToReevaluate;
64 BuildPropertyGroupCollection propertyGroups;
66 TaskDatabase taskDatabase;
67 TargetCollection targets;
68 DateTime timeOfLastDirty;
69 UsingTaskCollection usingTasks;
70 XmlDocument xmlDocument;
73 static XmlNamespaceManager manager;
74 static string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
77 : this (Engine.GlobalEngine)
81 public Project (Engine engine)
83 parentEngine = engine;
85 buildEnabled = ParentEngine.BuildEnabled;
86 xmlDocument = new XmlDocument ();
87 xmlDocument.PreserveWhitespace = false;
88 xmlDocument.AppendChild (xmlDocument.CreateElement ("Project", XmlNamespace));
89 xmlDocument.DocumentElement.SetAttribute ("xmlns", ns);
91 fullFileName = String.Empty;
93 globalProperties = new BuildPropertyGroup (null, this, null, false);
94 foreach (BuildProperty bp in parentEngine.GlobalProperties)
95 GlobalProperties.AddProperty (bp.Clone (true));
100 [MonoTODO ("Not tested")]
101 public void AddNewImport (string importLocation,
102 string importCondition)
104 if (importLocation == null)
105 throw new ArgumentNullException ("importLocation");
107 XmlElement importElement = xmlDocument.CreateElement ("Import", XmlNamespace);
108 xmlDocument.DocumentElement.AppendChild (importElement);
109 importElement.SetAttribute ("Project", importLocation);
110 if (!String.IsNullOrEmpty (importCondition))
111 importElement.SetAttribute ("Condition", importCondition);
113 Import import = new Import (importElement, this, null);
114 imports.Add (import);
115 MarkProjectAsDirty ();
119 public BuildItem AddNewItem (string itemName,
122 return AddNewItem (itemName, itemInclude, false);
125 [MonoTODO ("Adds item not in the same place as MS")]
126 public BuildItem AddNewItem (string itemName,
128 bool treatItemIncludeAsLiteral)
132 if (itemGroups.Count == 0)
133 big = AddNewItemGroup ();
135 BuildItemGroup [] groups = new BuildItemGroup [itemGroups.Count];
136 itemGroups.CopyTo (groups, 0);
140 BuildItem item = big.AddNewItem (itemName, itemInclude, treatItemIncludeAsLiteral);
142 MarkProjectAsDirty ();
148 [MonoTODO ("Not tested")]
149 public BuildItemGroup AddNewItemGroup ()
151 XmlElement element = xmlDocument.CreateElement ("ItemGroup", XmlNamespace);
152 xmlDocument.DocumentElement.AppendChild (element);
154 BuildItemGroup big = new BuildItemGroup (element, this, null, false);
155 itemGroups.Add (big);
156 MarkProjectAsDirty ();
162 [MonoTODO ("Ignores insertAtEndOfProject")]
163 public BuildPropertyGroup AddNewPropertyGroup (bool insertAtEndOfProject)
165 XmlElement element = xmlDocument.CreateElement ("PropertyGroup", XmlNamespace);
166 xmlDocument.DocumentElement.AppendChild (element);
168 BuildPropertyGroup bpg = new BuildPropertyGroup (element, this, null, false);
169 propertyGroups.Add (bpg);
170 MarkProjectAsDirty ();
176 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
177 public void AddNewUsingTaskFromAssemblyFile (string taskName,
180 if (taskName == null)
181 throw new ArgumentNullException ("taskName");
182 if (assemblyFile == null)
183 throw new ArgumentNullException ("assemblyFile");
185 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
186 xmlDocument.DocumentElement.AppendChild (element);
187 element.SetAttribute ("TaskName", taskName);
188 element.SetAttribute ("AssemblyFile", assemblyFile);
190 UsingTask ut = new UsingTask (element, this, null);
192 MarkProjectAsDirty ();
195 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
196 public void AddNewUsingTaskFromAssemblyName (string taskName,
199 if (taskName == null)
200 throw new ArgumentNullException ("taskName");
201 if (assemblyName == null)
202 throw new ArgumentNullException ("assemblyName");
204 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
205 xmlDocument.DocumentElement.AppendChild (element);
206 element.SetAttribute ("TaskName", taskName);
207 element.SetAttribute ("AssemblyName", assemblyName);
209 UsingTask ut = new UsingTask (element, this, null);
211 MarkProjectAsDirty ();
214 [MonoTODO ("Does nothing")]
220 [MonoTODO ("Not tested")]
221 public bool Build (string targetName)
223 return Build (new string [1] { targetName });
226 [MonoTODO ("Not tested")]
227 public bool Build (string[] targetNames)
229 return Build (targetNames, null);
232 [MonoTODO ("Not tested")]
233 public bool Build (string[] targetNames,
234 IDictionary targetOutputs)
236 return Build (targetNames, targetOutputs, BuildSettings.None);
239 [MonoTODO ("Not tested")]
240 public bool Build (string[] targetNames,
241 IDictionary targetOutputs,
242 BuildSettings buildFlags)
246 ParentEngine.StartBuild ();
249 if (targetNames.Length == 0) {
250 if (defaultTargets != null && defaultTargets.Length != 0)
251 targetNames = defaultTargets;
252 else if (firstTargetName != null)
253 targetNames = new string [1] { firstTargetName};
258 foreach (string target in targetNames) {
259 if (!targets.Exists (target))
260 // FIXME: test if it's logged
263 if (!targets [target].Build ())
271 public string[] GetConditionedPropertyValues (string propertyName)
273 if (conditionedProperties.ContainsKey (propertyName))
274 return conditionedProperties [propertyName].ToArray ();
276 return new string [0];
279 public BuildItemGroup GetEvaluatedItemsByName (string itemName)
281 if (needToReevaluate) {
282 needToReevaluate = false;
286 if (evaluatedItemsByName.ContainsKey (itemName))
287 return evaluatedItemsByName [itemName];
289 return new BuildItemGroup ();
292 public BuildItemGroup GetEvaluatedItemsByNameIgnoringCondition (string itemName)
294 if (needToReevaluate) {
295 needToReevaluate = false;
299 if (evaluatedItemsByNameIgnoringCondition.ContainsKey (itemName))
300 return evaluatedItemsByNameIgnoringCondition [itemName];
302 return new BuildItemGroup ();
305 public string GetEvaluatedProperty (string propertyName)
307 if (needToReevaluate) {
308 needToReevaluate = false;
312 if (propertyName == null)
313 throw new ArgumentNullException ("propertyName");
315 BuildProperty bp = evaluatedProperties [propertyName];
317 return bp == null ? null : (string) bp;
320 [MonoTODO ("We should remember that node and not use XPath to get it")]
321 public string GetProjectExtensions (string id)
323 if (id == null || id == String.Empty)
326 XmlNode node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
331 return node.InnerXml;
335 public void Load (string projectFileName)
337 this.fullFileName = Path.GetFullPath (projectFileName);
338 DoLoad (new StreamReader (projectFileName));
341 [MonoTODO ("Not tested")]
342 public void Load (TextReader textReader)
344 fullFileName = String.Empty;
348 public void LoadXml (string projectXml)
350 fullFileName = String.Empty;
351 DoLoad (new StringReader (projectXml));
352 MarkProjectAsDirty ();
356 public void MarkProjectAsDirty ()
359 timeOfLastDirty = DateTime.Now;
362 [MonoTODO ("Not tested")]
363 public void RemoveAllItemGroups ()
365 int length = ItemGroups.Count;
366 BuildItemGroup [] groups = new BuildItemGroup [length];
367 ItemGroups.CopyTo (groups, 0);
369 for (int i = 0; i < length; i++)
370 RemoveItemGroup (groups [i]);
372 MarkProjectAsDirty ();
376 [MonoTODO ("Not tested")]
377 public void RemoveAllPropertyGroups ()
379 int length = PropertyGroups.Count;
380 BuildPropertyGroup [] groups = new BuildPropertyGroup [length];
381 PropertyGroups.CopyTo (groups, 0);
383 for (int i = 0; i < length; i++)
384 RemovePropertyGroup (groups [i]);
386 MarkProjectAsDirty ();
391 public void RemoveItem (BuildItem itemToRemove)
393 if (itemToRemove == null)
394 throw new ArgumentNullException ("itemToRemove");
396 if (!itemToRemove.FromXml && !itemToRemove.HasParent)
397 throw new InvalidOperationException ("The object passed in is not part of the project.");
399 BuildItemGroup big = itemToRemove.ParentItemGroup;
401 if (big.Count == 1) {
402 // ParentItemGroup for items from xml and that have parent is the same
403 groupingCollection.Remove (big);
405 if (big.ParentProject != this)
406 throw new InvalidOperationException ("The object passed in is not part of the project.");
408 if (itemToRemove.FromXml)
409 big.RemoveItem (itemToRemove);
411 big.RemoveItem (itemToRemove.ParentItem);
414 MarkProjectAsDirty ();
418 [MonoTODO ("Not tested")]
419 public void RemoveItemGroup (BuildItemGroup itemGroupToRemove)
421 if (itemGroupToRemove == null)
422 throw new ArgumentNullException ("itemGroupToRemove");
424 groupingCollection.Remove (itemGroupToRemove);
425 MarkProjectAsDirty ();
429 // NOTE: does not modify imported projects
430 public void RemoveItemGroupsWithMatchingCondition (string matchingCondition)
432 throw new NotImplementedException ();
436 public void RemoveItemsByName (string itemName)
438 if (itemName == null)
439 throw new ArgumentNullException ("itemName");
441 throw new NotImplementedException ();
444 [MonoTODO ("Not tested")]
445 public void RemovePropertyGroup (BuildPropertyGroup propertyGroupToRemove)
447 if (propertyGroupToRemove == null)
448 throw new ArgumentNullException ("propertyGroupToRemove");
450 groupingCollection.Remove (propertyGroupToRemove);
451 MarkProjectAsDirty ();
455 // NOTE: does not modify imported projects
456 public void RemovePropertyGroupsWithMatchingCondition (string matchCondition)
458 throw new NotImplementedException ();
462 public void ResetBuildStatus ()
464 throw new NotImplementedException ();
467 public void Save (string projectFileName)
469 Save (projectFileName, Encoding.Default);
473 public void Save (string projectFileName, Encoding encoding)
475 xmlDocument.Save (projectFileName);
479 public void Save (TextWriter outTextWriter)
481 xmlDocument.Save (outTextWriter);
485 public void SetImportedProperty (string propertyName,
486 string propertyValue,
488 Project importProject)
490 SetImportedProperty (propertyName, propertyValue, condition, importProject,
491 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
494 public void SetImportedProperty (string propertyName,
495 string propertyValue,
497 Project importedProject,
498 PropertyPosition position)
500 SetImportedProperty (propertyName, propertyValue, condition, importedProject,
501 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
505 public void SetImportedProperty (string propertyName,
506 string propertyValue,
508 Project importedProject,
509 PropertyPosition position,
510 bool treatPropertyValueAsLiteral)
512 throw new NotImplementedException ();
515 public void SetProjectExtensions (string id, string xmlText)
518 throw new ArgumentNullException ("id");
520 throw new ArgumentNullException ("xmlText");
522 XmlNode projectExtensions, node;
524 projectExtensions = xmlDocument.SelectSingleNode ("/tns:Project/tns:ProjectExtensions", XmlNamespaceManager);
526 if (projectExtensions == null) {
527 projectExtensions = xmlDocument.CreateElement ("ProjectExtensions", XmlNamespace);
528 xmlDocument.DocumentElement.AppendChild (projectExtensions);
530 node = xmlDocument.CreateElement (id, XmlNamespace);
531 node.InnerXml = xmlText;
532 projectExtensions.AppendChild (node);
534 node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
537 node = xmlDocument.CreateElement (id, XmlNamespace);
538 projectExtensions.AppendChild (node);
541 node.InnerXml = xmlText;
545 MarkProjectAsDirty ();
548 public void SetProperty (string propertyName,
549 string propertyValue)
551 SetProperty (propertyName, propertyValue, "true",
552 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
555 public void SetProperty (string propertyName,
556 string propertyValue,
559 SetProperty (propertyName, propertyValue, condition,
560 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
563 public void SetProperty (string propertyName,
564 string propertyValue,
566 PropertyPosition position)
568 SetProperty (propertyName, propertyValue, condition,
569 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
573 public void SetProperty (string propertyName,
574 string propertyValue,
576 PropertyPosition position,
577 bool treatPropertyValueAsLiteral)
579 throw new NotImplementedException ();
582 internal void Unload ()
587 internal void CheckUnloaded ()
590 throw new InvalidOperationException ("This project object has been unloaded from the MSBuild engine and is no longer valid.");
593 internal void NeedToReevaluate ()
595 needToReevaluate = true;
598 // Does the actual loading.
599 void DoLoad (TextReader textReader)
602 ParentEngine.RemoveLoadedProject (this);
604 XmlReaderSettings settings = new XmlReaderSettings ();
606 if (SchemaFile != null) {
607 settings.Schemas.Add (null, SchemaFile);
608 settings.ValidationType = ValidationType.Schema;
609 settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
612 XmlReader xmlReader = XmlReader.Create (textReader, settings);
613 xmlDocument.Load (xmlReader);
615 if (xmlDocument.DocumentElement.Name != "Project") {
616 throw new InvalidProjectFileException (String.Format (
617 "The element <{0}> is unrecognized, or not supported in this context.", xmlDocument.DocumentElement.Name));
620 if (xmlDocument.DocumentElement.GetAttribute ("xmlns") != ns) {
621 throw new InvalidProjectFileException (
622 @"The default XML namespace of the project must be the MSBuild XML namespace." +
623 " If the project is authored in the MSBuild 2003 format, please add " +
624 "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" to the <Project> element. " +
625 "If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format. ");
628 ParentEngine.AddLoadedProject (this);
629 } catch (Exception e) {
630 throw new InvalidProjectFileException (e.Message, e);
643 groupingCollection = new GroupingCollection (this);
644 imports = new ImportCollection (groupingCollection);
645 usingTasks = new UsingTaskCollection (this);
646 itemGroups = new BuildItemGroupCollection (groupingCollection);
647 propertyGroups = new BuildPropertyGroupCollection (groupingCollection);
648 targets = new TargetCollection (this);
650 taskDatabase = new TaskDatabase ();
651 if (ParentEngine.DefaultTasksRegistered)
652 taskDatabase.CopyTasks (ParentEngine.DefaultTasks);
654 if (xmlDocument.DocumentElement.GetAttributeNode ("DefaultTargets") != null)
655 defaultTargets = xmlDocument.DocumentElement.GetAttribute ("DefaultTargets").Split (';');
657 defaultTargets = new string [0];
659 ProcessElements (xmlDocument.DocumentElement, null);
665 internal void ProcessElements (XmlElement rootElement, ImportedProject ip)
667 foreach (XmlNode xn in rootElement.ChildNodes) {
668 if (xn is XmlElement) {
669 XmlElement xe = (XmlElement) xn;
671 case "ProjectExtensions":
672 AddProjectExtensions (xe);
683 AddUsingTask (xe, ip);
689 AddItemGroup (xe, ip);
691 case "PropertyGroup":
692 AddPropertyGroup (xe, ip);
698 throw new InvalidProjectFileException ("Invalid element in project file.");
706 evaluatedItems = new BuildItemGroup (null, this, null, true);
707 evaluatedItemsIgnoringCondition = new BuildItemGroup (null, this, null, true);
708 evaluatedItemsByName = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
709 evaluatedItemsByNameIgnoringCondition = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
710 evaluatedProperties = new BuildPropertyGroup (null, null, null, true);
712 InitializeProperties ();
714 groupingCollection.Evaluate ();
716 //FIXME: UsingTasks aren't really evaluated. (shouldn't use expressions or anything)
717 foreach (UsingTask usingTask in UsingTasks)
718 usingTask.Evaluate ();
721 void InitializeProperties ()
725 foreach (BuildProperty gp in GlobalProperties) {
726 bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
727 EvaluatedProperties.AddProperty (bp);
730 foreach (DictionaryEntry de in Environment.GetEnvironmentVariables ()) {
731 bp = new BuildProperty ((string) de.Key, (string) de.Value, PropertyType.Environment);
732 EvaluatedProperties.AddProperty (bp);
735 EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildBinPath", parentEngine.BinPath, PropertyType.Reserved));
737 // FIXME: make some internal method that will work like GetDirectoryName but output String.Empty on null/String.Empty
739 if (FullFileName == String.Empty)
740 projectDir = Environment.CurrentDirectory;
742 projectDir = Path.GetDirectoryName (FullFileName);
744 EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDirectory", projectDir, PropertyType.Reserved));
747 void AddProjectExtensions (XmlElement xmlElement)
751 void AddMessage (XmlElement xmlElement)
755 void AddTarget (XmlElement xmlElement, ImportedProject importedProject)
757 Target target = new Target (xmlElement, this, importedProject);
758 targets.AddTarget (target);
760 if (firstTargetName == null)
761 firstTargetName = target.Name;
764 void AddUsingTask (XmlElement xmlElement, ImportedProject importedProject)
768 usingTask = new UsingTask (xmlElement, this, importedProject);
769 UsingTasks.Add (usingTask);
772 void AddImport (XmlElement xmlElement, ImportedProject importingProject)
776 import = new Import (xmlElement, this, importingProject);
777 Imports.Add (import);
780 void AddItemGroup (XmlElement xmlElement, ImportedProject importedProject)
782 BuildItemGroup big = new BuildItemGroup (xmlElement, this, importedProject, false);
783 ItemGroups.Add (big);
786 void AddPropertyGroup (XmlElement xmlElement, ImportedProject importedProject)
788 BuildPropertyGroup bpg = new BuildPropertyGroup (xmlElement, this, importedProject, false);
789 PropertyGroups.Add (bpg);
792 void AddChoose (XmlElement xmlElement)
794 BuildChoose bc = new BuildChoose (xmlElement, this);
795 groupingCollection.Add (bc);
798 static void ValidationCallBack (object sender, ValidationEventArgs e)
800 Console.WriteLine ("Validation Error: {0}", e.Message);
803 public bool BuildEnabled {
808 buildEnabled = value;
812 public Encoding Encoding {
813 get { return encoding; }
816 public string DefaultTargets {
818 return xmlDocument.DocumentElement.GetAttribute ("DefaultTargets");
821 xmlDocument.DocumentElement.SetAttribute ("DefaultTargets", value);
822 defaultTargets = value.Split (';');
826 public BuildItemGroup EvaluatedItems {
828 if (needToReevaluate) {
829 needToReevaluate = false;
832 return evaluatedItems;
836 public BuildItemGroup EvaluatedItemsIgnoringCondition {
838 if (needToReevaluate) {
839 needToReevaluate = false;
842 return evaluatedItemsIgnoringCondition;
846 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByName {
848 // FIXME: do we need to do this here?
849 if (needToReevaluate) {
850 needToReevaluate = false;
853 return evaluatedItemsByName;
857 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByNameIgnoringCondition {
859 // FIXME: do we need to do this here?
860 if (needToReevaluate) {
861 needToReevaluate = false;
864 return evaluatedItemsByNameIgnoringCondition;
868 public BuildPropertyGroup EvaluatedProperties {
870 if (needToReevaluate) {
871 needToReevaluate = false;
874 return evaluatedProperties;
878 public string FullFileName {
879 get { return fullFileName; }
880 set { fullFileName = value; }
883 public BuildPropertyGroup GlobalProperties {
884 get { return globalProperties; }
887 throw new ArgumentNullException ("value");
890 throw new InvalidOperationException ("GlobalProperties can not be set to persisted property group.");
892 globalProperties = value;
897 public bool IsDirty {
898 get { return isDirty; }
901 public bool IsValidated {
902 get { return isValidated; }
903 set { isValidated = value; }
906 public BuildItemGroupCollection ItemGroups {
907 get { return itemGroups; }
910 public ImportCollection Imports {
911 get { return imports; }
914 public string InitialTargets {
915 get { return initialTargets; }
916 set { initialTargets = value; }
919 public Engine ParentEngine {
920 get { return parentEngine; }
923 public BuildPropertyGroupCollection PropertyGroups {
924 get { return propertyGroups; }
927 public string SchemaFile {
928 get { return schemaFile; }
929 set { schemaFile = value; }
932 public TargetCollection Targets {
933 get { return targets; }
936 public DateTime TimeOfLastDirty {
937 get { return timeOfLastDirty; }
940 public UsingTaskCollection UsingTasks {
941 get { return usingTasks; }
946 get { return xmlDocument.InnerXml; }
949 internal static XmlNamespaceManager XmlNamespaceManager {
951 if (manager == null) {
952 manager = new XmlNamespaceManager (new NameTable ());
953 manager.AddNamespace ("tns", ns);
960 internal TaskDatabase TaskDatabase {
961 get { return taskDatabase; }
964 internal XmlDocument XmlDocument {
965 get { return xmlDocument; }
968 internal static string XmlNamespace {