// In here, we're defining a class, foo_Task, derived from our DefinedTask class. This allows us to write the bulk of the code // in real C#, rather than attempting to build it here. // This means that we have Task <- DefinedTask <- foo_Task. // We also need a module and an assembly to hold the class, so we do that, too. protected override void ExecuteTask() { AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = _taskName + "_Assembly"; AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(_taskName + "_Module"); // Now we've got an assembly and a module for the task to live in, we can define the actual task class. TypeBuilder typeBuilder = moduleBuilder.DefineType(_taskName + "_Task", TypeAttributes.Public); typeBuilder.SetParent(typeof(DefinedTask)); // It needs a [TaskName] attribute. ConstructorInfo taskNameAttributeConstructor = typeof(TaskNameAttribute).GetConstructor(new Type[] { typeof(string) }); CustomAttributeBuilder taskNameAttributeBuilder = new CustomAttributeBuilder(taskNameAttributeConstructor, new object[] { _taskName }); typeBuilder.SetCustomAttribute(taskNameAttributeBuilder); // We're done. Create it. Type taskType = typeBuilder.CreateType(); // Stash the XML in our static. We'll need it in DefinedTask later. DefinedTaskDefinitions.Add(_taskName, XmlNode); // Hook that up into NAnt. TaskBuilder taskBuilder = new TaskBuilder(taskType.Assembly, taskType.FullName); TypeFactory.TaskBuilders.Add(taskBuilder); }
protected override void ExecuteTask() { Log(Level.Info, "Executing defined task."); // When you call a defined task, you can define any XML attributes that you want. // We take those, and convert them to properties called "this.whatever". This makes // them available to the enclosed XML with predictable names. foreach (XmlAttribute attr in XmlNode.Attributes) { string thisPropertyName = "this." + attr.Name; string thisPropertyValue = Properties.ExpandProperties(attr.Value, Location); Properties.Add(thisPropertyName, thisPropertyValue); } // DefineTask created a class derived from DefinedTask. Pick up the [TaskName] attribute from that derived class. TaskNameAttribute taskNameAttribute = (TaskNameAttribute)Attribute.GetCustomAttribute(GetType(), typeof(TaskNameAttribute)); // We stashed the enclosed XML node in the DefintedTaskDefinitions global collection; pick it up now. XmlNode originalDefinitionNode = DefinedTaskDefinitions.Find(taskNameAttribute.Name); // NAnt conveniently already has a way to nest tasks: TaskContainer. This is how <if>, <foreach/do>, etc., work. // We need to define our own derived class to get access to some of the protected properties. DefinedTaskContainer containedTasks = DefinedTaskContainer.Create(this, originalDefinitionNode); try { containedTasks.Execute(); } finally { foreach (XmlAttribute attr in XmlNode.Attributes) { Properties.Remove("this." + attr.Name); } } }