簡體   English   中英

使用自定義規則進行動態驗證

[英]Dynamic validation using custom rules

我已經使用.Net 語言 4 年了。 I develop 3 tier and 5 tier applications using WCF, ASP.NET for web applications, and C# for windows applications. 每次我開始一個項目時,業務規則和驗證都是一個問題。

我應該在哪里放置自定義驗證規則(按鈕單擊事件、頁面加載或在我的類中的 setter/getter 中)?

如果一個項目很大並且只有一個字段而不是 5 個字符應該是 7 個字符 - 為什么要重建整個項目(或業務類項目)?

我想如果我有一個包含自定義規則的文件,那么當需要更改時,我可以簡單地在其中放置一個新規則。 我已經閱讀了互聯網上的一些文章,這些文章為此提供了基於 XML 的文件,但這似乎有問題,因為:

  • XML 文件中沒有 Intellisense 和錯誤很難找到
  • 我們必須編寫自定義 XML 解析器
  • 由於此方法需要多次轉換,因此非常慢

我的問題:

是否有使用 .NET 方法(反射、表達式樹、Lambda 表達式、動態、DLL 的運行時創建等)的設計模式或其他任何方法來使用自定義規則進行動態驗證?


編輯 1)

屬性呢? 我們可以將它們與反射到自定義驗證一起使用嗎? 我們可以使用這種方法根據另一個屬性(例如 P1 應該是 P2+1)來驗證一個屬性嗎?

表示業務規則的最佳方式是在 xml 中。 要充分利用這種表示法,您應該從定義規則引擎數據 model 的結構開始,即回答這些問題。

  1. 都有些什么樣的規矩?
  2. 規則可以分類嗎?
  3. 規則是否包含常見的屬性(屬性),例如允許的值、格式等?

完成此操作后,創建一個虛擬規則 xml,然后基於此 xml 派生一個 xml 模式。 xsd.exe工具可以幫助您創建架構。 如果您可以使用Altova XmlSpy 之類的工具,則更容易創建架構。

至於您的具體問題的答案,

  • 我們無法使用 Intellisense,如果 XML 文件中有錯誤,則很難找到它。

架構就緒后,Visual Studio 會為創建 xml(包括智能感知和驗證)提供充足的支持。

  • 我們應該編寫一個自定義的 xml 解析器

不需要, XmlSerializer Class提供了序列化/反序列化的邏輯,即將規則 xml 轉換為規則數據 model,反之亦然。

  • 因為這種方法需要多次鑄造,所以速度很慢

好吧,與硬編碼規則(作為類嵌入到程序集中的規則)相比,這是一個部分有效的觀點,但這種方法的靈活性遠遠超過了任何性能缺點。 如果規則發生變化,您無需重新構建解決方案。 在大多數情況下,性能影響很小。

除非您有嚴格的性能標准,否則 xml 方法是實現規則引擎的首選方法。 請記住,您的架構耦合越松散,運行時的靈活性就越高,但會對性能產生負面影響。

示例規則

<RulesEngine>
  <Rules>
    <Rule Id="Rule1">
      <Function>
        <Equals>
          <Property name="Property1" classId="MyClassId"/>
            <Sum>
              <Property name="Property2" classId="MyClassId"/>
              <Constant type="UInt16" value="1"/>
            </Sum>
          </Equals>
        </Function>
      </Rule>
    </Rules>
    <Classes>
    <Class name="MyNamespace.MyClass" Id="MyClassId">
      <Property name="Property1" type="UInt16"/>
      <Property name="Property2" type="UInt16"/>
    </Class>
  </Classes>
</RulesEngine>

規則引擎需要解釋此規則並相應地推斷其含義。

看看FluentValidation 它使用表達式,您可以創建條件驗證(例如,如果這些屬性滿足某些條件,則驗證這些屬性)。 FV 可能不是開箱即用的動態,但您可以獲得智能感知、表現力和類型安全性。 它的通用性意味着它運行得相當快。 您可以通過傳入驗證委托或自定義驗證器來注入一些運行時動態,它們可以做任何您能想到的事情。

這確實意味着您必須重新編譯,但您可以將驗證器放在單獨的程序集中。 驗證器不在class 中/在 class 中確實有意義,因為您經常發現驗證是在context中執行的。 例如,如果汽車有所有輪子,它可能是有效的。 但是,如果你試圖駕駛它並且它沒有汽油電池,那么它對於駕駛是“無效的”。 也就是說,我會將規則定位為“接近”它們正在驗證的內容,因為它們是您域的一部分。

如果您需要依賴於一個或多個屬性(包括其自身)的屬性的規則,並且如果不滿足規則的條件,則需要自定義消息,您可以這樣做。 考慮一下:

RuleFor(x => x.P1)
    .Must(x => x.P1 > x.P2)
    .Message("P1 must be one more than P2. P1 was {0}; P2 was {1}", x=>x.P1, x=>x.P2);

給出了一個簡單的比較,但你可以做一些更復雜的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM