patterncsharpMinor
Fluent Interface for a XmlQueryBuilder
Viewed 0 times
xmlquerybuilderinterfacefluentfor
Problem
In this answer I suggested using a fluent interface "builder" to replace all the hard-coded, repetitive and quite error-prone inline XML string concatenations.
This code might need a bit of tweaking to work perfectly with the OP's code in the question this code is following-up on, but it seems to work as expected. Thoughts?
```
public class XmlQueryBuilder
where TEntity : class
{
private readonly XDocument _xDoc = new XDocument();
private readonly XElement _queryNode = new XElement("query");
public XmlQueryBuilder()
{
var rootNode = new XElement("queryxml");
rootNode.SetAttributeValue("version", "1.0");
var entityNode = new XElement("entity");
entityNode.Value = typeof (TEntity).Name;
rootNode.Add(entityNode);
_xDoc.Add(rootNode);
}
public XmlQueryBuilder Where(Expression> property, XmlQueryOperator operation, string value)
{
var xCondition = new XElement("condition");
var xField = new XElement("field");
xField.Value = GetPropertyName(property);
var xExpression = new XElement("expression");
xExpression.SetAttributeValue("op", operation.ToString());
xExpression.Value = value;
xField.Add(xExpression);
xCondition.Add(xField);
_queryNode.Add(xCondition);
return this;
}
public override string ToString()
{
var parent = _xDoc.Element("queryxml");
if (parent == null) throw new InvalidOperationException("root node was not created.");
parent.Add(_queryNode);
return _xDoc.ToString();
}
private string GetPropertyName(Expression> propertyLambda)
{
// credits http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression/672212#672212 (modified to return property name)
var type = typeof(
This code might need a bit of tweaking to work perfectly with the OP's code in the question this code is following-up on, but it seems to work as expected. Thoughts?
public enum XmlQueryOperator
{
Equals,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual
}```
public class XmlQueryBuilder
where TEntity : class
{
private readonly XDocument _xDoc = new XDocument();
private readonly XElement _queryNode = new XElement("query");
public XmlQueryBuilder()
{
var rootNode = new XElement("queryxml");
rootNode.SetAttributeValue("version", "1.0");
var entityNode = new XElement("entity");
entityNode.Value = typeof (TEntity).Name;
rootNode.Add(entityNode);
_xDoc.Add(rootNode);
}
public XmlQueryBuilder Where(Expression> property, XmlQueryOperator operation, string value)
{
var xCondition = new XElement("condition");
var xField = new XElement("field");
xField.Value = GetPropertyName(property);
var xExpression = new XElement("expression");
xExpression.SetAttributeValue("op", operation.ToString());
xExpression.Value = value;
xField.Add(xExpression);
xCondition.Add(xField);
_queryNode.Add(xCondition);
return this;
}
public override string ToString()
{
var parent = _xDoc.Element("queryxml");
if (parent == null) throw new InvalidOperationException("root node was not created.");
parent.Add(_queryNode);
return _xDoc.ToString();
}
private string GetPropertyName(Expression> propertyLambda)
{
// credits http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression/672212#672212 (modified to return property name)
var type = typeof(
Solution
ToString() does too many things, it should only be calling _xDoc.ToString(); it has side-effects that make it dangerous to call more than once:var foo = builder.ToString()
Console.WriteLine(builder.ToString());
Console.ReadLine();Will not produce the expected output, and will not throw an exception either, resulting in an XML document with
_queryNode showing up as many times as ToString() was called.Code Snippets
var foo = builder.ToString()
Console.WriteLine(builder.ToString());
Console.ReadLine();Context
StackExchange Code Review Q#49003, answer score: 4
Revisions (0)
No revisions yet.