- Home
- LLBLGen Pro
- Custom Templates
Preset Parameter Parsing Task Performer
Joined: 26-Aug-2006
Hello,
do we (license holders) have access to the application core source code. I had this idea to add some functionality between the generator and the taskperformers that would enumerate through parameters and replace keywords (such as [projectName]) with appropriate values.
Could even make it run off some XML file so you could configure something like:
<keywords>
<keyword name="projectName" value="%Project%.ProjectName" />
<keywords>
%Project% evaluates to the instance of Project and then u just DataBinder.Eval to get the value of the property.
I've been hunting around the source code packages that I have but it doesn't look like ApplicationCore is part of it.
Joined: 26-Aug-2006
So it doesn't look like ApplicationCore is available to play with. I think I've found another way to get the job done with a task performer.
Below is some rough preliminary code as a proof of concept. What this is doing is looping through the tasks defined in the preset and doing a replace on all the string typed parameter values. If it finds [projectName] it replaces it with the actual project name. If it finds [rootNameSpace] it replaces it with the actual project namespace.
Its a bit crappy that way it blasts everything with a Replace, but at this point i'm not too fussed. I may put some regular expressions into play, but I dont see it being neccessary - theres no requirement for performance.
So you would put this in as the first task to run. It chugs away modifying all the parameters then things start working.
At this point I'm going to look at adding some (non-compile time) configurability to it.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using SD.LLBLGen.Pro.ApplicationCore;
using SD.LLBLGen.Pro.GeneratorCore;
using SD.LLBLGen.Pro.ApplicationCore.Tasks;
namespace OAMPS.TaskPerformers
{
public class ParameterFilter : TaskPerformerBase
{
bool result = false;
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition, Dictionary<string, SD.LLBLGen.Pro.ApplicationCore.Tasks.TaskParameter> parameters)
{
ITaskGroup tasks = executingGenerator.TasksToExecute;
foreach (ITaskGroupElement item in tasks)
{
if (item.Name == taskDefinition.Name)
continue;
ITask task = item as ITask;
if (task != null)
{
foreach (TaskParameter parm in task.Parameters.Values)
{
if (parm.ValueType == TaskParameterValueType.String)
{
parm.Value = parm.Value.Replace("[projectName]", executingGenerator.ProjectDefinition.ProjectName);
parm.Value = parm.Value.Replace("[rootNameSpace]", executingGenerator.ProjectDefinition.RootNameSpace);
}
}
}
System.Diagnostics.Debug.WriteLine(item.Name);
RecurseTaskGroup(item, executingGenerator);
}
result = true;
}
void RecurseTaskGroup(ITaskGroupElement item, SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator)
{
ITask task = item as ITask;
ITaskGroup group = item as ITaskGroup;
if (task != null)
{
foreach (TaskParameter parm in task.Parameters.Values)
{
if (parm.ValueType == TaskParameterValueType.String)
{
parm.Value = parm.Value.Replace("[projectName]", executingGenerator.ProjectDefinition.ProjectName);
parm.Value = parm.Value.Replace("[rootNameSpace]", executingGenerator.ProjectDefinition.RootNameSpace);
}
}
}
else
{
foreach (ITaskGroupElement element in group)
RecurseTaskGroup(element, executingGenerator);
}
}
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition)
{
throw new GeneratorAbortException("No parameters have been specified. Aborting generator.", taskDefinition);
}
public override bool PerformResult
{
get { return result; }
}
}
}
Joined: 26-Aug-2006
Added support for reading in the values of project custom properties. Also the first time I've used anonymous methods!
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using SD.LLBLGen.Pro.ApplicationCore;
using SD.LLBLGen.Pro.GeneratorCore;
using SD.LLBLGen.Pro.ApplicationCore.Tasks;
using System.Text.RegularExpressions;
namespace OAMPS.TaskPerformers
{
public class ParameterFilter : TaskPerformerBase
{
bool result = false;
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition, Dictionary<string, SD.LLBLGen.Pro.ApplicationCore.Tasks.TaskParameter> parameters)
{
throw new GeneratorAbortException("No parameters are required. Aborting generator.", taskDefinition);
}
void RecurseTaskGroup(ITaskGroupElement item, SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator)
{
ITask task = item as ITask;
ITaskGroup group = item as ITaskGroup;
if (task != null)
{
ProcessItem(task, executingGenerator);
}
else
{
foreach (ITaskGroupElement element in group)
RecurseTaskGroup(element, executingGenerator);
}
}
void ProcessItem(ITask task, SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator)
{
foreach (TaskParameter parm in task.Parameters.Values)
{
if (parm.ValueType == TaskParameterValueType.String)
{
parm.Value = parm.Value.Replace("[projectName]", executingGenerator.ProjectDefinition.ProjectName);
parm.Value = parm.Value.Replace("[rootNameSpace]", executingGenerator.ProjectDefinition.RootNameSpace);
Regex exp = new Regex("(\\[customProperty:(?<propertyName>[\\w\\s]+))\\]");
parm.Value = exp.Replace(parm.Value, delegate(Match match)
{
string propertyName = match.Groups["propertyName"].Value;
if (executingGenerator.ProjectDefinition.CustomProperties.ContainsKey(propertyName))
{
string propertyValue = (string)executingGenerator.ProjectDefinition.CustomProperties[propertyName];
return propertyValue;
}
return propertyName;
});
}
}
}
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition)
{
ITaskGroup tasks = executingGenerator.TasksToExecute;
foreach (ITaskGroupElement item in tasks)
{
if (item.Name == taskDefinition.Name)
continue;
ITask task = item as ITask;
if (task != null)
{
ProcessItem(task, executingGenerator);
}
System.Diagnostics.Debug.WriteLine(item.Name);
RecurseTaskGroup(item, executingGenerator);
}
result = true;
}
public override bool PerformResult
{
get { return result; }
}
}
}
Joined: 26-Aug-2006
This next mod basically gives u a pointer to the ProjectDefinition. Just do something like
[project:RootNameSpace]
or
[project:ProjectCreator]
. The code just reflects the value off the project instance. Also you can use properties of properties for example:
[project:Properties.ConnectionStringKeyName]
.
I used System.Web.UI.DataBinder.Eval to do the reflection cause I'm lazy. This had the annoying side affect of requiring a reference to System.Web.dll. What DataBinder.Eval does is pretty simple, I may add my own implementation later.
The [projectName] and [rootNameSpace] placeholders no longer work. You should use
[project:ProjectName]
.
Enjoy!
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using SD.LLBLGen.Pro.ApplicationCore;
using SD.LLBLGen.Pro.GeneratorCore;
using SD.LLBLGen.Pro.ApplicationCore.Tasks;
using System.Text.RegularExpressions;
namespace OAMPS.TaskPerformers
{
public class ParameterFilter : TaskPerformerBase
{
bool result = false;
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition, Dictionary<string, SD.LLBLGen.Pro.ApplicationCore.Tasks.TaskParameter> parameters)
{
throw new GeneratorAbortException("No parameters are required. Aborting generator.", taskDefinition);
}
void RecurseTaskGroup(ITaskGroupElement item, SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator)
{
ITask task = item as ITask;
ITaskGroup group = item as ITaskGroup;
if (task != null)
{
ProcessItem(task, executingGenerator);
}
else
{
foreach (ITaskGroupElement element in group)
RecurseTaskGroup(element, executingGenerator);
}
}
void ProcessItem(ITask task, SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator)
{
foreach (TaskParameter parm in task.Parameters.Values)
{
if (parm.ValueType == TaskParameterValueType.String)
{
Regex customExp = new Regex("(\\[customProperty:(?<propertyName>[\\w\\s]+))\\]");
parm.Value = customExp.Replace(parm.Value, delegate(Match match)
{
string propertyName = match.Groups["propertyName"].Value;
if (executingGenerator.ProjectDefinition.CustomProperties.ContainsKey(propertyName))
{
string propertyValue = (string)executingGenerator.ProjectDefinition.CustomProperties[propertyName];
return propertyValue;
}
return propertyName;
});
Regex projectExp = new Regex("(\\[project:(?<propertyName>[\\w\\s]+))\\]");
parm.Value = projectExp.Replace(parm.Value, delegate(Match match)
{
string propertyName = match.Groups["propertyName"].Value;
return Convert.ToString(System.Web.UI.DataBinder.Eval(executingGenerator.ProjectDefinition, propertyName));
});
}
}
}
public override void Perform(SD.LLBLGen.Pro.ApplicationCore.IGenerator executingGenerator, SD.LLBLGen.Pro.ApplicationCore.ITask taskDefinition)
{
ITaskGroup tasks = executingGenerator.TasksToExecute;
foreach (ITaskGroupElement item in tasks)
{
if (item.Name == taskDefinition.Name)
continue;
ITask task = item as ITask;
if (task != null)
{
ProcessItem(task, executingGenerator);
}
System.Diagnostics.Debug.WriteLine(item.Name);
RecurseTaskGroup(item, executingGenerator);
}
result = true;
}
public override bool PerformResult
{
get { return result; }
}
}
}
Joined: 17-Aug-2003
Thanks for sharing! Do you want me to alter the title of the thread?
I see you ran into a bug in the new UBB parser: 4 spaces in code snippets isn't formatted correctly. Will correct that too
ApplicationCore is part of the designer, so the sourcecode isn't available to you.
The new forum has attachment capabilities, so we'll open a template share forum soon
Joined: 26-Aug-2006
Yeah ok alter the title to "Amazing Parameter Parser"
...Or perhaps something less flamboyant.
Attachments sounds good. Looking forward to it.
Joined: 17-Aug-2003
worldspawn wrote:
Yeah ok alter the title to "Amazing Parameter Parser"
...Or perhaps something less flamboyant.
I'm not sure if this title I gave it now covers the task performer.
Attachments sounds good. Looking forward to it.
Ok, first the bugs in the UBB parser, as you can see your code didn't format properly, and then I'll setup new forums.
Joined: 26-Aug-2006
I'm not sure if this title I gave it now covers the task performer.
Hmm... "Preset Parameter Parsing Task Performer". It's more of a "parse" than a "replace".
Any thoughts about implementing something like this in the official release?
Joined: 17-Aug-2003
What's the particular problem this task performer solves? (I skimmed over the code, didn't look in depth into it to understand what exactly it solves)
(edit: reposted your posts with the updated ubb parser, so the layout is now correct)
Joined: 26-Aug-2006
What it does is recurse through all the tasks in the preset and modify any parameters of type string. It looks for placeholders and then replaces them as appropriate.
So if for a directory creator task performer i enter in
[project:RootNameSpace]
as the value for the folderName parameter it will be replaced by the value of the RootNameSpace property of the executing generator's Project instance. (thats one thing it does - also
[customProperty:PropertyName]
and
[generator:Property]
.
It does (for project) with this regular expression.
Regex projectExp = new Regex("(\\[project:(?<propertyName>[\\w\\s]+))\\]");
The value is replaced like this:
foreach (TaskParameter parm in task.Parameters.Values)
{
if (parm.ValueType != TaskParameterValueType.String)
continue;//this was return - which was a bug.
parm.Value = projectExp.Replace(parm.Value, delegate(Match match)
{
string propertyName = match.Groups["propertyName"].Value;
return Convert.ToString(System.Web.UI.DataBinder.Eval(executingGenerator.ProjectDefinition, propertyName));
});
//do other placeholders
}
(I think) it's cool because you can now read anything (any property or indexed value) out of the Project instance.