using System.Collections.Generic;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Sdk.Query;
static void Main(string[] args)
var xmlDocument = XDocument.Parse(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='new_grantacquittaltermexpense'>
<attribute name='new_grantacquittaltermexpenseid' />
<attribute name='new_id' />
<attribute name='createdon' />
<attribute name='new_supplier' />
<attribute name='new_regardinggrantacquittaltermdetailid' />
<attribute name='new_gstapplicable' />
<attribute name='new_expensesamountexgst' />
<order attribute='new_id' descending='false' />
<condition attribute='statecode' operator='eq' value='0' />
<condition attribute='new_expensewaived' operator='eq' value='1' />
<condition attribute='new_expensedecision' operator='eq' value='100000001' />
<condition attribute='new_expensedecision' operator='eq' value='100000000' />
var entityPost = new Entity("new_grantacquittaltermexpense");
entityPost.Attributes.Add("statecode", 0);
entityPost.Attributes.Add("new_expensedecision", new OptionSetValue(100000001));
entityPost.Attributes.Add("new_expensewaived", true);
var entityPostFail = new Entity("new_grantacquittaltermexpense");
entityPostFail.Attributes.Add("statecode", 0);
entityPostFail.Attributes.Add("new_expensedecision", new OptionSetValue(100000001));
entityPostFail.Attributes.Add("new_expensewaived", false);
var filterNode = xmlDocument.Element("fetch").Element("entity").Element("filter");
var result = VerifyFilterAndChildFilterConditionsAreMet(entityPost, filterNode);
var failResult = VerifyFilterAndChildFilterConditionsAreMet(entityPostFail, filterNode);
public static bool VerifyFilterAndChildFilterConditionsAreMet(Entity callingEntityPostImage, XElement filter)
var filterTypeValue = filter.Attribute("type").Value;
var filterLogicalOperator = filter.Attribute("type").Value == "and" ? LogicalOperator.And : LogicalOperator.Or;
var filterConditions = filter.Elements("condition");
var filterResult = false;
var childFilterResults = new List<bool>();
var filterConditionResults = new List<bool>();
var childFilters = filter.Elements("filter");
foreach (var childFilter in childFilters)
childFilterResults.Add(VerifyFilterAndChildFilterConditionsAreMet(callingEntityPostImage, childFilter));
foreach (var filterCondition in filterConditions)
var attributeName = filterCondition.Attribute("attribute").Value;
var conditionOperator = filterCondition.Attribute("operator").Value;
var conditionValue = filterCondition.Attribute("value").Value;
if (!callingEntityPostImage.Attributes.Contains(attributeName))
filterConditionResults.Add(false);
Func<object, object, bool> valueComparer = CreateConditionComparer(conditionOperator);
var attributeValue = callingEntityPostImage.Attributes[attributeName];
var attributeValueType = attributeValue.GetType();
switch (attributeValueType.Name)
var castAttributeValue = (bool)attributeValue;
var castExpectedValue = Convert.ToBoolean(Convert.ToInt32(conditionValue));
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var castAttributeValue = ((OptionSetValue)attributeValue).Value;
var castExpectedValue = Convert.ToInt32(conditionValue);
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var castAttributeValue = ((EntityReference)attributeValue).Id;
var castExpectedValue = Guid.Parse(conditionValue);
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var castAttributeValue = ((Money)attributeValue).Value;
var castExpectedValue = Convert.ToDecimal(conditionValue);
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var castAttributeValue = (int)attributeValue;
var castExpectedValue = Convert.ToInt32(conditionValue);
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var castAttributeValue = (string)attributeValue;
var castExpectedValue = conditionValue;
filterConditionResults.Add(valueComparer(castAttributeValue, castExpectedValue));
var filterConditionResult = true;
if (filterConditionResults.Any())
if (filterTypeValue == "or")
filterConditionResult = filterConditionResults.Any(result => result);
else if (filterTypeValue == "and")
filterConditionResult = filterConditionResults.Any() && filterConditionResults.All(result => result);
if (childFilterResults.Any())
if (filterTypeValue == "or")
filterResult = filterConditionResult || childFilterResults.Any(result => result);
else if (filterTypeValue == "and")
filterResult = filterConditionResult && childFilterResults.All(result => result);
filterResult = filterConditionResult;
private static Func<object, object, bool> CreateConditionComparer(string conditionOperator)
Func<object, object, bool> conditionComparer;
switch (conditionOperator)
conditionComparer = (valueOne, valueTwo) => valueOne.Equals(valueTwo);
conditionComparer = (valueOne, valueTwo) => !valueOne.Equals(valueTwo);
throw new InvalidPluginExecutionException("Unidentified target condition found in rollup configuration: {conditionOperator}");
return conditionComparer;