3

当我尝试以下 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" />

我尝试了几种设置过滤器的组合,但找不到解决方案。

我错过了什么?

4

1 回答 1

1

Filter()扩展采用对象集合并根据给定规则单独评估它们。规则引擎采用集合元素的类型,并使用它来编译带有该类型参数的 lambda。

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

规则1.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>

规则2.xml

这条规则就是你应该拥有的方式。它适用于System.Xml.Linq.XElement类型的对象。因此,它只能对该类型的属性和方法进行操作,即您不会获得自定义字段 id、addr、name 等。

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

规则3.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>
于 2017-07-25T06:15:19.553 回答