Codeeffects Linq Error: E106 This ruleset does not contain rules of type System.Xml.Linq.XElement

When I try to use the following LINQ filter

  var productsInfo = from product in productsElement.Descendants("product").Filter(rule)
                           from photo in product.Descendants("photo")
                           from parameter in product.Descendants("parameter")
                           let id = product.Attribute("id")
                           let addr = photo.Attribute("addr")
                           let name = parameter.Attribute("name")
                           select new { ID = id.Value, Addr = addr.Value, Name = name.Value };

      

I am getting the following error:

The given ruleset does not contain any rules with type
System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 (Error E106)

      

My rule:

<?xml version="1.0" encoding="utf-8"?><codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4"><rule id="09973a56-3d6a-4616-ae1c-40d0d17e95b9" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="testSlimWebRule.products, testSlimWebRule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" eval="true"><definition><condition type="equal"><property name="AllProducts.product.id" /><value type="numeric">1</value></condition></definition><format><lines /></format></rule></codeeffects>

      

XML:

 XDocument productsElement = XDocument.Parse(@"<products>
        <AllProducts>
             <product id='1'>
                 <photo addr='1.jpg'/>
                 <parameter name='name'/>
             </product>
             <product id='2'>
                 <photo addr='2.jpg'/>
                 <parameter name='Kenneth'/>
             </product>
          </AllProducts>
        </products> ");

      

Product class generated with Visual Studio "Insert as XML class":

namespace testSlimWebRule
{
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class products
{

    private productsAllProducts allProductsField;

    /// <remarks/>
    public productsAllProducts AllProducts
    {
        get
        {
            return this.allProductsField;
        }
        set
        {
            this.allProductsField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProducts
{

    private productsAllProductsProduct productField;

    /// <remarks/>
    public productsAllProductsProduct product
    {
        get
        {
            return this.productField;
        }
        set
        {
            this.productField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProduct
{

    private productsAllProductsProductPhoto photoField;

    private productsAllProductsProductParameter parameterField;

    private byte idField;

    /// <remarks/>
    public productsAllProductsProductPhoto photo
    {
        get
        {
            return this.photoField;
        }
        set
        {
            this.photoField = value;
        }
    }

    /// <remarks/>
    public productsAllProductsProductParameter parameter
    {
        get
        {
            return this.parameterField;
        }
        set
        {
            this.parameterField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public byte id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProductPhoto
{

    private string addrField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string addr
    {
        get
        {
            return this.addrField;
        }
        set
        {
            this.addrField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class productsAllProductsProductParameter
{

    private string nameField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name
    {
        get
        {
            return this.nameField;
        }
        set
        {
            this.nameField = value;
        }
    }
}


}

      

Part of ASP.net:

  <rule:RuleEditor ID="ruleEditor" runat="server"
                Mode="Filter"
                ShowToolBar="false"
                SourceAssembly="testSlimWebRule"
                SourceType="testSlimWebRule.products" />

      

I've tried several combinations of filter setting but just can't seem to find a solution.

What am I missing?

+3


source to share


1 answer


The Filter () extension takes a collection of objects and evaluates them according to a separate rule. The rules engine takes the type of the collection item and uses it to compile the lambda with a parameter of that type.

List<MyClass> list = new List<MyClass>();
list.Filter(rule);

      

In this example, the rule is of type MyClass and it applies to every object in the list like:

Evaluator<MyClass> ev = new Evaluator<MyClass>(rule);
foreach (var item in list)
{
    ev.Evaluate(item);
}

      

You can read more information on the CodeEffects documentation page: Rule-Based Data Filtering Using LINQ to Object Provider .

In your example, you made several mistakes:

  • You generate classes for XML elements, but you don't use them.
  • Auto-generated classes do not display the AllProduct field correctly. It is assumed to be an array of Products.
  • You are filtering on a collection of XElement objects, but the rule is of type testSlimWebRule.products. In this case, there should be an XElement.

The example below will show four possible options, with the first being the best.

home

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;
using CodeEffects.Rule.Core;

namespace testSlimWebRule
{
    class Program
    {
        /* Output:
         * Option A: 1, Bob, 1.jpg
         * Option B: 1, Bob, 1.jpg
         * Option C: 1, Bob, 1.jpg
         * Option D: 2, Kenneth, 2.jpg
         */
        static void Main(string[] args)
        {
            string xml =
                @"<products>
                    <AllProducts>
                        <product id='1'>
                            <photo addr='1.jpg'/>
                            <parameter name='Bob'/>
                        </product>
                        <product id='2'>
                            <photo addr='2.jpg'/>
                            <parameter name='Kenneth'/>
                        </product>
                    </AllProducts>
                </products>";

            XDocument dom = XDocument.Parse(xml);

            products products;
            //You need to load auto-generated classes. I prefer serialization. You may parse XML elements individually.
            using (var xmlReader = dom.CreateReader())
            {
                var serializer = new XmlSerializer(typeof(products));
                products = (products)serializer.Deserialize(xmlReader);
            }

            string productsProductRule = File.ReadAllText("rule1.xml");

            //A: Filter productsProduct[]; result is IEnumerable<productsProduct>.
            //This rule evaluates objects of the productsProduct type.
            var filteredProducts = products.AllProducts.Filter(productsProductRule);
            foreach (var product in filteredProducts)
                Console.WriteLine("Option A: {0}, {1}, {2}", product.id, product.parameter.name, product.photo.addr);

            string xElementRule = File.ReadAllText("rule2.xml");

            //B: Filter IEnumerable<XElement>; result is IEnumerable<XElement>.
            //This rule evaluates objects of the XElement type.
            var filteredElements = dom.Descendants("product").Filter(xElementRule);
            foreach (var element in filteredElements)
                Console.WriteLine("Option B: {0}, {1}, {2}", element.Attribute("id").Value, element.Element("parameter").Attribute("name").Value, element.Element("photo").Attribute("addr").Value);

            //C: Filter IEnumerable<XElement>; result is IEnumerable<'a> (anonymous)
            //This rule also evaluates objects of the XElement type.
            var productsInfo = from product in dom.Descendants("product").Filter(xElementRule)
                               from photo in product.Descendants("photo")
                               from parameter in product.Descendants("parameter")
                               let id = product.Attribute("id")
                               let addr = photo.Attribute("addr")
                               let name = parameter.Attribute("name")
                               select new
                               {
                                   ID = id.Value,
                                   Addr = addr.Value,
                                   Name = name.Value
                               };

            foreach (var info in productsInfo)
                Console.WriteLine("Option C: {0}, {1}, {2}", info.ID, info.Name, info.Addr);

            string anonymousRule = File.ReadAllText("rule3.xml");

            //D: Filter IEnumerable<'a>; result is IEnumerable<'a>
            //This rule evaluates objects of the anonymous type 'a with properties ID, Addr, and Name.
            var productsInfo2 = (from product in dom.Descendants("product")
                                 from photo in product.Descendants("photo")
                                 from parameter in product.Descendants("parameter")
                                 let id = product.Attribute("id")
                                 let addr = photo.Attribute("addr")
                                 let name = parameter.Attribute("name")
                                 select new
                                 {
                                     ID = id.Value,
                                     Addr = addr.Value,
                                     Name = name.Value
                                 })
                                .Filter(anonymousRule);

            foreach (var info in productsInfo2)
                Console.WriteLine("Option D: {0}, {1}, {2}", info.ID, info.Name, info.Addr);
        }
    }
}

      

Auto-generated classes



You need to re-insert your XML example to create the correct array fields. The one you have was generated with a sample XML that only had one entry. However, you need a collection to filter.

using System;

namespace testSlimWebRule
{

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class products
    {

        private productsProduct[] allProductsField;

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("product", IsNullable = false)]
        public productsProduct[] AllProducts
        {
            get
            {
                return this.allProductsField;
            }
            set
            {
                this.allProductsField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class productsProduct
    {

        private productsProductPhoto photoField;

        private productsProductParameter parameterField;

        private byte idField;

        /// <remarks/>
        public productsProductPhoto photo
        {
            get
            {
                return this.photoField;
            }
            set
            {
                this.photoField = value;
            }
        }

        /// <remarks/>
        public productsProductParameter parameter
        {
            get
            {
                return this.parameterField;
            }
            set
            {
                this.parameterField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public byte id
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class productsProductPhoto
    {

        private string addrField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string addr
        {
            get
            {
                return this.addrField;
            }
            set
            {
                this.addrField = value;
            }
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class productsProductParameter
    {

        private string nameField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name
        {
            get
            {
                return this.nameField;
            }
            set
            {
                this.nameField = value;
            }
        }
    }
}

      

rule1.xml

This rule is of the correct type testSlimWebRule.productsProduct. It is evaluated on each item in the autogenerated testSlimWebRule.productsProduct array.

<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
    <rule id="09973a56-3d6a-4616-ae1c-40d0d17e95b9" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="testSlimWebRule.productsProduct, testSlimWebRule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" eval="true">
        <definition>
            <condition type="equal">
                <property name="id" />
                <value type="numeric">1</value>
            </condition>
        </definition>
    </rule>
</codeeffects>

      

rule2.xml

This rule is the way you would do it. It applies to objects of type System.Xml.Linq.XElement. Thus, it can only work with properties and methods of this type, i.e. You don't get your own id, addr, name, etc. fields.

<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
    <rule id="e38da351-1190-47fb-b99b-d06787c9a459" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" eval="true">
        <definition>
            <condition type="equal">
                <property name="FirstAttribute.Value" />
                <value>1</value>
            </condition>
        </definition>
    </rule>
</codeeffects>

      

rule3.xml

This rule is of no type. Instead, it gets whatever type it evaluates to. In this example, it gets the anonymous type 'a, so it can work with Property IDs, Name and Addr.

<?xml version="1.0" encoding="utf-8"?>
<codeeffects xmlns="http://codeeffects.com/schemas/rule/41" xmlns:ui="http://codeeffects.com/schemas/ui/4">
    <rule id="7d72463f-5ae2-4617-a2bf-fd605fcb4f54" webrule="4.3.6.7" utc="2017-07-24T10:07:08.6346" type="" eval="true">
        <definition>
            <condition type="startsWith">
                <property name="Addr" />
                <value>2</value>
            </condition>
        </definition>
    </rule>
</codeeffects>

      

+1


source







All Articles