程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> Asp.net 面向接口可擴展框架之業務規則引擎擴展模塊,業務規則擴展模塊

Asp.net 面向接口可擴展框架之業務規則引擎擴展模塊,業務規則擴展模塊

編輯:C#入門知識

Asp.net 面向接口可擴展框架之業務規則引擎擴展模塊,業務規則擴展模塊


隨著面向接口可擴展框架的繼續開發,有些功能開發出現了"瓶頸",有太多的東西要寫死才好做。但寫死的代碼擴展性是非常的不好,迷茫中尋找出入...

進而想到我以前開發的好幾個項目,都已有一定的可配置能力,想想怎麼把這些地方的代碼抽象提取出來。進而想到"業務規則引擎",網上找了幾個都不太入"眼",就抽時間再造個"輪子"

業務規則引擎在很多成熟的工作流引擎中都有相應的模塊,是工作流的核心之一。但是除了工作流很多業務都需要業務規則引擎,所以它非常有必要獨立作為一個模塊。

在現實中很多項目開發都需要一些定制化的分支需求,為了這些需求把項目搞的雞飛狗跳。使用業務規則引擎來做邏輯分支路由、參數“矯正”、攔截等,說是如虎添翼應該不為過。


 這裡使用社區發文章來做個例子

1、先看文章相關模型

A:ArticleRepository是文章數據倉儲,實際是把文章存放在內存的List中

B:User是文章作者,Article就是文章了,ArticlePublish是DTO,包含文章和作者的信息

2、文章有不同的分類

        ArticleRepository TopArticles = new ArticleRepository { Name = "置頂" };
        ArticleRepository PerfectArticles = new ArticleRepository { Name = "精華" };
        ArticleRepository NetArticles = new ArticleRepository { Name = ".Net" };
        ArticleRepository OtherArticles = new ArticleRepository { Name = "其他" };

A:其中分為.net文章和其他文章,另外還有“置頂”和“精華”兩個推送分類

B:文章現在分為.net文章和其他文章兩個分類,以後很難說不用增加Java、PHP等其他分類,所以這個地方需要可擴展

C:不是每個人發的文章都置頂和精華,要不就沒法愉快的玩耍了

3、可以按授權進行推送

先看授權相關建模

為了簡單明了,這裡都是用內存對象來模擬存儲

A:Role是角色,角色有個權重的字段(Sort),Sort值越大權限越大

(有人說角色不應該是平等的嗎?通過綁定資源來控制權限?我想問國家主席和你們村主任能平等嗎?角色特權和資源綁定等手段應該綜合來用。再者我們是演示業務規則引擎的,不是專門討論權限系統的,先打住)

B:RolePermission用於授權(Grant)和獲取權限(判斷權限),維護者一個用戶和權限的關聯關系

public class RolePermission : IEntityAccess<User, Role>, IComparer<Role> { private Dictionary<User, Role> _permission = new Dictionary<User, Role>(); public bool Grant(User user, Role role) { Role role0 = Get(user); if (role0 != null && role0.Sort >= role.Sort) return true; _permission[user] = role; return true; } public Role Get(User user) { Role role = null; _permission.TryGetValue(user, out role); return role; } int IComparer<Role>.Compare(Role x, Role y) { return Comparer<Role>.Default.Compare(x, y); } } RolePermission

4、繼續場景設置

        Role manager = new Role { Id = 1, Name = "管理員", Sort = 9999 };
        Role expert = new Role { Id = 2, Name = "專家", Sort = 999 };
        User user1 = new User { Id = 1, Name = "張三", Year = 3 };
        User user2 = new User { Id = 2, Name = "李四", Year = 10 };
        User user3 = new User { Id = 3, Name = "王二", Year = 0 };

5、現在可以開始發文章了 

            RolePermission permission = new RolePermission();
            ConfigRole(permission);
            ArticlePublish post1 = new ArticlePublish(user1, new Article { Content = ".Net" });
            ArticlePublish post2 = new ArticlePublish(user2, new Article { Content = "Java" });
            ArticlePublish post3 = new ArticlePublish(user3, new Article { Content = "Php" });
            Engine<ArticlePublish, int> engine = new Engine<ArticlePublish, int>();
            ConfigCategory(engine);
            Post(engine, post1, post2, post3);
            Show(TopArticles, PerfectArticles, NetArticles, OtherArticles);
private void ConfigRole(RolePermission permission) { permission.Grant(user3, expert); } 授權代碼 private static void Post(Engine<ArticlePublish, int> engine, params ArticlePublish[] articles) { foreach (var item in articles) { int id = 0; if (engine.Run(item, ref id)) Console.WriteLine(string.Concat("文章處理成功,Id=", id.ToString())); } } 發表文章代碼 private static void Show(params ArticleRepository[] repositorys) { foreach (var repository in repositorys) { Console.WriteLine(new string('-', 80)); List<Article> list = repository.ListAll(); if (list.Count < 1) { Console.WriteLine(string.Concat(repository.Name, " 無")); continue; } Console.WriteLine(repository.Name); foreach (var item in list) { Console.WriteLine(string.Concat("Article{Id=", item.Id, ",Content=", item.Content, "}")); } Console.WriteLine(new string('-', 80)); } } 顯示所有文章代碼
文章處理成功,Id=1
文章處理成功,Id=2
文章處理成功,Id=3
--------------------------------------------------------------------------------

置頂 無
--------------------------------------------------------------------------------

精華 無
--------------------------------------------------------------------------------

.Net
Article{Id=1,Content=.Net}
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

其他
Article{Id=2,Content=Java}
Article{Id=3,Content=Php}
--------------------------------------------------------------------------------

三篇文章發表成功,一篇.net,兩篇其他,效果非常不錯

先等等,Engine<ArticlePublish, int>是什麼鬼,要發文章不應該是ArticleRepository嗎?

Engine就是大名鼎鼎的業務規則引擎了,ArticleRepository發表文章不假,但是都是由Engine決定發不發,用誰發,這些就是業務規則,

(ArticleRepository就是只負責存儲和讀取,職責非常單一)

6、把業務規則定義看一下

        private void ConfigCategory(Engine<ArticlePublish, int> engine)
        {
            engine.When(post => post.Article.Content.Contains(".Net")).Then(post => NetArticles.Add(post.Article));
            engine.Then(post => OtherArticles.Add(post.Article));
        }

非常簡單,如果文章包含.net關鍵字,使用NetArticles存儲,否則使用OtherArticles存儲(分表就是這麼簡單!!!)

 7、繼續推送的例子

            Engine<ArticlePublish, int> pushEngine = new Engine<ArticlePublish, int>();
            ConfigPush(permission, pushEngine);
            ConfigYear(pushEngine);
            Post(pushEngine, post1, post2, post3);
            Show(TopArticles, PerfectArticles, NetArticles, OtherArticles);
文章處理成功,Id=2
文章處理成功,Id=3
--------------------------------------------------------------------------------

置頂
Article{Id=3,Content=Php}
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

精華
Article{Id=2,Content=Java}
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

.Net
Article{Id=1,Content=.Net}
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

其他
Article{Id=2,Content=Java}
Article{Id=3,Content=Php}
--------------------------------------------------------------------------------

 這次在置頂和精華都各有一篇了

8、我們看一下推送規則是怎麼定義的

        private void ConfigPush(RolePermission permission, Engine<ArticlePublish, int> engine)
        {
            int topNum = 0;
            int topLimit = 1;
            engine.When(post => topNum < topLimit && Comparer<Role>.Default.Compare(permission.Get(post.User), expert) >= 0).Then(post => { topNum++; return TopArticles.Add(post.Article); });
            engine.When(post => Comparer<Role>.Default.Compare(permission.Get(post.User), expert) >= 0).Then(post => PerfectArticles.Add(post.Article));
        }
        private void ConfigYear(Engine<ArticlePublish, int> engine)
        {
            engine.When(post => post.User.Year >= 8).Then(post => PerfectArticles.Add(post.Article));
        }

解讀一下

A:if 專家及以上權限且可以發置頂,推送到置頂(先來先得)

B:else if 專家發的文章推送到精華

C:else if 8年以上會員發的文章推送到精華

D:else 什麼都不做

注:先不要和我掰扯以上業務規則的合理性,只是個測試例子而已

就是這麼簡單,老板再也不用擔心我不會寫業務規則了

 

 以上都是使用Fluent代碼來做業務規則配置的,以後我還需要做使用文件配置做動態業務規則的例子,以便在容器配置文件中使用

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved