{"id":24523620,"url":"https://github.com/devfoundries/logicengine","last_synced_at":"2025-06-20T10:09:02.021Z","repository":{"id":20951048,"uuid":"24239570","full_name":"DevFoundries/LogicEngine","owner":"DevFoundries","description":"Logic engine is designed to run arbitrary rules or bits of logic against a given model","archived":false,"fork":false,"pushed_at":"2017-02-20T22:53:36.000Z","size":551,"stargazers_count":11,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-11T09:23:14.039Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DevFoundries.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-09-19T17:50:48.000Z","updated_at":"2024-01-27T12:21:10.000Z","dependencies_parsed_at":"2022-08-30T21:31:16.008Z","dependency_job_id":null,"html_url":"https://github.com/DevFoundries/LogicEngine","commit_stats":null,"previous_names":["wbsimms/logicengine"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/DevFoundries/LogicEngine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevFoundries%2FLogicEngine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevFoundries%2FLogicEngine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevFoundries%2FLogicEngine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevFoundries%2FLogicEngine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DevFoundries","download_url":"https://codeload.github.com/DevFoundries/LogicEngine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevFoundries%2FLogicEngine/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260924533,"owners_count":23083524,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-22T04:16:10.478Z","updated_at":"2025-06-20T10:08:57.008Z","avatar_url":"https://github.com/DevFoundries.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\r\n![LogicEngine Status](https://ci.appveyor.com/api/projects/status/github/wbsimms/logicengine?svg=true)\r\n\r\n[![Get help on Codementor](https://cdn.codementor.io/badges/get_help_github.svg)](https://www.codementor.io/wbsimms?utm_source=github\u0026utm_medium=button\u0026utm_term=wbsimms\u0026utm_campaign=github)\r\n\r\nLogicEngine\r\n===========\r\n\r\nLogicEngine is designed to run arbitrary rules or bits of logic against a given model. It's written in C# .NET 4.6.2 and supports:\r\n- .NET 4.0\r\n- .NET 4.5\r\n- .NET 4.6+\r\n\r\nThis project is born out of a DRY (don't repeat yourself) mentality. In other words, I was using the same code on several projects.\r\n\r\nHow to use\r\n-----------\r\n\r\nThe source code has a working example (ExampleEngine) which shows how easy the logic engine is to use. The steps to use LogicEngine are as follows:\r\n1. Create your business model\r\n```C#\r\npublic class ExampleModel\r\n{\r\n    public int Value1 { get; set; }\r\n    public int Value2 { get; set; }\r\n    public int AddResult { get; set; }\r\n    public int SubtractResult { get; set; }\r\n    public int MultiplicaionResult { get; set; }\r\n    public float DivisionResult { get; set; }\r\n}\r\n```\r\n2. Create rules which implement IRule\\\u003cT\u003e\r\n```c#\r\npublic class AddRule : IRule\u003cExampleModel\u003e \r\n{\r\n    public IEngineResult Execute(ExampleModel model)\r\n    {\r\n        EngineResult result = new EngineResult() { Name = GetType().ToString() };\r\n        model.AddResult = model.Value1 + model.Value2;\r\n        return result;\r\n    }\r\n}\r\n```\r\n3. Add the rules to the rule collection\r\n4. Create the engine with the collection\r\n5. Execute the engine with your business model\r\n\r\n```c#\r\nEngine\u003cExampleModel\u003e engine = new Engine\u003cExampleModel\u003e(\r\n    new RuleCollection\u003cExampleModel\u003e()\r\n    {\r\n        new AddRule(), \r\n        new DivisionRule(), \r\n        new MultiplicationRule(), \r\n        new SubtractRule()\r\n    }) {RunBumperRules = true};\r\nvar retval = engine.Execute(model);\r\n```\r\n\r\nThe engine has the following interface:\r\n```c#\r\npublic interface IEngine\u003cT\u003e \r\n\twhere T: class \r\n{\r\n    IList\u003cIEngineResult\u003e Execute(T model);\r\n    bool RunBumperRules { get; set; }\r\n    TimeSpan RunElapsed { get; }\r\n}\r\n```\r\nRunBumperRulles will insert PreRun and PostRun rules as the first and last rules. These are used to determine RunElapsed timespan.\r\n\r\nThe engine returns a list of IEngineResult:\r\n```c#\r\npublic interface IEngineResult\r\n{\r\n    string Name { get; set; }\r\n    bool HasError { get; }\r\n    string Error { get; set; }\r\n    string Message { get; set; }\r\n    DateTime TimeStart { get; }\r\n    DateTime TimeEnd { get; }\r\n    TimeSpan Elapsed { get; }\r\n    IEngineResult End(); // You should never need to call this.\r\n}\r\n```\r\nEach IEngineResult will return the Elapsed TimeSpan. It's your reponsiblity to set Name, Error, and Message.\r\n\r\nAPI\r\n-----------\r\n\r\nThe only real requirement is to implement the IRule interface:\r\n\r\n```c#\r\npublic interface IRule\u003cT\u003e where T : class\r\n{\r\n    IEngineResult Execute(T model);\r\n}\r\n```\r\n\r\nIn the ExampleEngine, the AddRule class looks like this:\r\n\r\n```c#\r\npublic class AddRule : IRule\u003cExampleModel\u003e \r\n{\r\n    public IEngineResult Execute(ExampleModel model)\r\n    {\r\n        EngineResult result = new EngineResult() { Name = GetType().ToString() };\r\n        model.AddResult = model.Value1 + model.Value2;\r\n        return result;\r\n    }\r\n}\r\n```\r\nThe EngineResult class can be implemented, or you can use your own. The Engine returns a list of EngineResults. You can add any information you'd like.\r\n\r\nOnce the rules are created, you only need to create an engine with them and execute the rules against the model.\r\n\r\n```c#\r\npublic IList\u003cIEngineResult\u003e Run(ExampleModel model)\r\n{\r\n    Engine\u003cExampleModel\u003e engine = new Engine\u003cExampleModel\u003e(\r\n        new RuleCollection\u003cExampleModel\u003e()\r\n        {\r\n            new AddRule(), \r\n            new DivisionRule(), \r\n            new MultiplicationRule(), \r\n            new SubtractRule()\r\n        }) {RunBumperRules = true};\r\n    var retval = engine.Execute(model);\r\n    return retval;\r\n}\r\n```\r\n\r\nBumper Rules\r\n------------\r\nThe engine has some \"bumper rules\". They're rules that run before/after all your rules. They will give you run start/stop times.\r\n\r\n```c#\r\nnew Engine\u003cSomeModel\u003e(someListOfRules) {RunBumperRules = true;}\r\n```\r\n\r\nResults Formatter\r\n------------\r\nThe engine has support for formatting the list of IEngineResults. There are two provided formatters:\r\n1. NoopFormatter\r\nThis formatter does nothing. It's the default formatter if you don't provide one.\r\n2. CsvFormatter\r\nThis formatter returns a CSV list of the results. NOTE: The first row will the total elapsed run time.\r\n\r\n```c#\r\npublic Engine(IRuleCollection\u003cT\u003e rules, IResultsFormatter resultFormatter = null)\r\n```\r\nThe only requirement to implement your own formatter is to implement the IResultsFormatter interface as seen in the CsvResultsFormatter:\r\n```c#\r\npublic interface IResultsFormatter\r\n{\r\n\tvoid OutputResults(IList\u003cIEngineResult\u003e results, TimeSpan totalTime);\r\n}\r\n\r\npublic class CsvResultsFormatter : ICsvResultsFormatter\r\n{\r\n\tpublic string Output { get; private set; }\r\n\tpublic void OutputResults(IList\u003cIEngineResult\u003e results, TimeSpan runElapsed)\r\n\t{\r\n\t\tvar format = \"{0},{1},{2},{3},{4},{5},{6}\\r\\n\";\r\n\t\tStringBuilder sb = new StringBuilder();\r\n\t\tsb.AppendLine(\"Run Elapsed Total Time: \" + runElapsed);\r\n\t\tsb.AppendFormat(format, \"RuleName\", \"Start\", \"Stop\", \"Elapsed\", \"HasError\",\"Message\" ,\"ErrorMessage\");\r\n\t\tforeach (var result in results)\r\n\t\t{\r\n\t\t\tsb.AppendFormat(format, result.Name, result.TimeStart,result.TimeEnd, result.Elapsed, result.HasError, result.Message,result.Error);\r\n\t\t}\r\n\t\tthis.Output = sb.ToString();\r\n\t}\r\n}\r\n```\r\n\r\nDependency Injection Support\r\n-----------\r\nYou can use dependency injection to add your rules. Simply add them to the RulesCollection.\r\n\r\n```c#\r\nUnityContainer container = new UnityContainer();\r\ncontainer.RegisterType\u003cIEngine\u003cstring\u003e,Engine\u003cstring\u003e\u003e();\r\ncontainer.RegisterType\u003cIResultsFormatter, NoopFormatter\u003e();\r\nIRuleCollection\u003cstring\u003e coll = new RuleCollection\u003cstring\u003e();\r\ncontainer.RegisterInstance(coll);\r\nvar engine = container.Resolve\u003cIEngine\u003cstring\u003e\u003e();\r\nAssert.IsNotNull(engine);\r\n```\r\n\r\n## Feature Requests ##\r\n[![Feature Requests](http://feathub.com/wbsimms/LogicEngine?format=svg)](http://feathub.com/wbsimms/LogicEngine)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevfoundries%2Flogicengine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevfoundries%2Flogicengine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevfoundries%2Flogicengine/lists"}