Codeeffects Linq Ошибка: E106 Данный набор правил не содержит правил с типом System.Xml.Linq.XElement

Когда я пытаюсь использовать следующий фильтр LINQ

  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 };

Я получаю следующую ошибку:

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)

Мое правило:

<?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> ");

Класс продуктов, созданный с помощью Visual Studio «Вставить как класс XML»:

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;
        }
    }
}


}

Часть ASP.net:

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

Я пробовал несколько комбинаций настройки фильтра, но никак не могу найти решение.

Что мне не хватает?


person Kenneth Roberts    schedule 24.07.2017    source источник


Ответы (1)


Расширение Filter () берет набор объектов и индивидуально оценивает их на соответствие заданному правилу. Механизм правил принимает тип элемента коллекции и использует его для компиляции лямбда-выражения с параметром этого типа.

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

В этом примере правило имеет тип MyClass и применяется к каждому объекту в списке аналогично:

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

Вы можете прочитать больше на странице документации CodeEffects: Фильтрация данных на основе правил Использование LINQ to Object Provider.

В вашем примере вы сделали несколько ошибок:

  1. Вы создаете классы для элементов XML, но не используете их.
  2. Автоматически созданные классы неправильно отображают поле AllProduct. Предполагается, что это массив productsProduct.
  3. Вы применяете фильтр к коллекции объектов XElement, но правило имеет тип testSlimWebRule.products. В этом случае это должен быть XElement.

Пример ниже демонстрирует четыре возможных варианта, первый из которых является лучшим.

Главный

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);
        }
    }
}

Автоматически созданные классы

Вам нужно повторно вставить свой XML-пример, чтобы сгенерировать правильные поля массива. Тот, который у вас есть, был сгенерирован с образцом XML, в котором была только одна запись. Однако для фильтрации вам понадобится коллекция.

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

Это правило имеет правильный тип testSlimWebRule.productsProduct. Он оценивается по каждому элементу автоматически сгенерированного массива testSlimWebRule.productsProduct.

<?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

Это правило так и должно быть у вас. Применяется к объектам типа System.Xml.Linq.XElement. Таким образом, он может работать только со свойствами и методами этого типа, то есть вы не получаете свои идентификаторы настраиваемых полей, адрес, имя и т. Д.

<?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

Это правило не имеет никакого типа. Вместо этого он получает тот тип, по которому оценивается. В этом примере он получает анонимный тип 'a, поэтому он может работать со свойствами ID, Name и 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>
person Ruslan    schedule 25.07.2017