{"id":22888370,"url":"https://github.com/baune8d/expressioncache","last_synced_at":"2026-01-08T21:15:51.157Z","repository":{"id":129464913,"uuid":"97413954","full_name":"Baune8D/ExpressionCache","owner":"Baune8D","description":"ExpressionCache takes advantage of expressions to generate and maintain cache keys for your application.","archived":false,"fork":false,"pushed_at":"2024-12-30T20:34:46.000Z","size":200,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-04T11:43:43.377Z","etag":null,"topics":["cache","csharp","dotnet"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Baune8D.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-07-16T22:03:49.000Z","updated_at":"2024-12-30T18:15:42.000Z","dependencies_parsed_at":"2024-07-30T23:33:53.897Z","dependency_job_id":"f28aa40a-a2a5-4c73-a7fb-e9c6bab800b0","html_url":"https://github.com/Baune8D/ExpressionCache","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Baune8D%2FExpressionCache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Baune8D%2FExpressionCache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Baune8D%2FExpressionCache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Baune8D%2FExpressionCache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Baune8D","download_url":"https://codeload.github.com/Baune8D/ExpressionCache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252873936,"owners_count":21817708,"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":["cache","csharp","dotnet"],"created_at":"2024-12-13T20:47:54.685Z","updated_at":"2026-01-08T21:15:51.040Z","avatar_url":"https://github.com/Baune8D.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExpressionCache\n[![Build status](https://ci.appveyor.com/api/projects/status/0abskdimkpe1m558?svg=true)](https://ci.appveyor.com/project/Baune8D/expressioncache)\n[![codecov](https://codecov.io/gh/Baune8D/expressioncache/branch/main/graph/badge.svg)](https://codecov.io/gh/Baune8D/expressioncache)\n\n| Package                     | Version                                                                                                                                 |\n| ----------------------------|:---------------------------------------------------------------------------------------------------------------------------------------:|\n| ExpressionCache.Core        | [![NuGet Badge](https://buildstats.info/nuget/ExpressionCache.Core)](https://www.nuget.org/packages/ExpressionCache.Core)               |\n| ExpressionCache.Distributed | [![NuGet Badge](https://buildstats.info/nuget/ExpressionCache.Distributed)](https://www.nuget.org/packages/ExpressionCache.Distributed) |\n\n**Dev feed:** [https://www.myget.org/F/baunegaard/api/v3/index.json](https://www.myget.org/F/baunegaard/api/v3/index.json)  \n\n## Table of Contents\n1. [ExpressionCache.Core](#expressionCache.core)\n2. [ExpressionCache.Distributed](#expressionCache.distributed)\n\n## ExpressionCache.Core\n\n### Key generation\nThe cache key will be a combination of class name, function name and parameter values.  \n\nThe following code snippet is the heart of the library:\n```csharp\npublic class SampleService\n{\n    private readonly IDistributedCacheService _cacheService;\n    private readonly SampleRepository _sampleRepository;\n\n    public SampleService(IDistributedCacheService cacheService, SampleRepository sampleRepository)\n    {\n        _cacheService = cacheService;\n        _sampleRepository = sampleRepository;\n    }\n\n    public async Task\u003cEntityModel\u003e GetAsync(int entityId, CacheAction cacheAction = CacheAction.Invoke)\n    {\n        if (cacheAction != CacheAction.Bypass)\n        {\n            return await _cacheService.InvokeCacheAsync(\n                () =\u003e GetAsync(entityId, CacheAction.Bypass),\n                TimeSpan.FromDays(1), cacheAction);\n        }\n\n        return await _sampleRepository.GetAsync(entityId);\n    }\n}\n```\n\n**Flow (Without an existing cache entry)**\n1. Lets say we call GetAsync(5) on the above snippet.\n2. cacheAction is not equal to Bypass, so InvokeCacheAsync gets called.\n3. A lookup in cache with generated key \\{SampleService}\\{GetAsync}\\{5}\\{Bypass} happens.\n4. No cache entry is found so the expression GetAsync(5, CacheAction.Bypass) is invoked.\n5. This time the cache is skipped because of Bypass. Result of sampleRepository is returned.\n6. The returned value gets cached and InvokeCacheAsync returns.\n\n### CacheAction enum\n1. **Invoke** - The default action. Will check for a cached value and return it if found.\n2. **Bypass** - Used to bypass the caching entirely. **Note!** Should always be used in the expression to InvokeCache.\n3. **Overwrite** - Skip checking for cached value, but still cache new value.\n\n### Object parameters\nIf complex objects are used as function parameters, ExpressionCache needs a way to know how to build the key value.\n\nBy extending **ICacheKey** one can define how to build the key.\n\n```csharp\npublic class SampleObject : ICacheKey\n{\n    public int Parameter1 { get; set; }\n    public int Parameter2 { get; set; }\n\n    public virtual void BuildCacheKey(ICacheKeyBuilder builder)\n    {\n        builder\n            .By(Parameter1)\n            .By(Parameter2);\n    }\n}\n```\n\n## ExpressionCache.Distributed\nExpressionCache use providers to support different caching engines.\n\nIncluded in this repository is ExpressionCache.Distributed which works with Microsofts IDistributedCache interface.\n\n### .NET Core Dependency Injection\nThe library include extensions for IServiceCollection interface.\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    // Register an IDistributedCache implementation.\n    services.AddDistributedRedisCache(options =\u003e\n    {\n        options.Configuration = \"localhost\";\n        options.InstanceName = \"Sample\";\n    });\n\n    // Register the distributed cache service.\n    services.AddDistributedExpressionCache();\n}\n```\nYou can now inject IDistributedCacheService using DI into you code.\n\n### Full service example\n```csharp\npublic class SampleService\n{\n    private readonly IDistributedCacheService _cacheService;\n    private readonly SampleRepository _sampleRepository;\n\n    public SampleService(IDistributedCacheService cacheService, SampleRepository sampleRepository)\n    {\n        _cacheService = cacheService;\n        _sampleRepository = sampleRepository;\n    }\n\n    public async Task\u003cbool\u003e CreateAsync(EntityDto entity)\n    {\n        var newId = await _sampleRepository.CreateAsync(entity);\n        if (newId \u003e 0)\n        {\n            // Add new entity to cache.\n            return await GetAsync(newId, CacheAction.Overwrite) != null;\n        }\n        return false;\n    }\n\n    public async Task\u003cbool\u003e UpdateAsync(EntityDto entity)\n    {\n        if (await _sampleRepository.UpdateAsync(entity))\n        {\n            // Overwrite cached entity with updated one.\n            return await GetAsync(entity.Id, CacheAction.Overwrite) != null;\n        }\n        return false;\n    }\n\n    public async Task\u003cbool\u003e DeleteAsync(int entityId)\n    {\n        if (await _sampleRepository.DeleteAsync(id)) \n        {\n            // Remove cached entity.\n            await _cacheService.RemoveAsync(() =\u003e GetAsync(entityId, CacheAction.Bypass));\n            return true;\n        }\n        return false;\n    }\n\n    public async Task\u003cEntityModel\u003e GetAsync(int entityId, CacheAction cacheAction = CacheAction.Invoke)\n    {\n        if (cacheAction != CacheAction.Bypass)\n        {\n            // Check for existing cached entity.\n            return await _cacheService.InvokeCacheAsync(\n                () =\u003e GetAsync(entityId, CacheAction.Bypass),\n                TimeSpan.FromDays(1), cacheAction);\n        }\n\n        // If not already cached, this result will get cached.\n        return await _sampleRepository.GetAsync(entityId);\n    }\n}\n```\n\n### Interface members\nThe full interface of IDistributedCacheService.  \n\n```csharp\npublic interface IExpressionCacheBase\n{\n    string GetKey\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    string GetKey\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n\n    TResult InvokeCache\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression, TimeSpan expiry, CacheAction cacheAction);\n    Task\u003cTResult\u003e InvokeCacheAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression, TimeSpan expiry, CacheAction cacheAction);\n}\n\npublic interface IDistributedCacheService : IExpressionCacheBase\n{\n    void Remove\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    void Remove\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n    Task RemoveAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    Task RemoveAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n\n    bool Exists\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    bool Exists\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n    Task\u003cbool\u003e ExistsAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    Task\u003cbool\u003e ExistsAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n\n    TResult Get\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    TResult Get\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n    Task\u003cTResult\u003e GetAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression);\n    Task\u003cTResult\u003e GetAsync\u003cTResult\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression);\n\n    Task\u003cList\u003cTResult\u003e\u003e GetManyAsync\u003cTResult\u003e(IEnumerable\u003cExpression\u003cFunc\u003cTResult\u003e\u003e\u003e expressions);\n    Task\u003cList\u003cTResult\u003e\u003e GetManyAsync\u003cTResult\u003e(IEnumerable\u003cExpression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e\u003e expressions);\n\n    void Set\u003cTResult, TValue\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression, TValue value, TimeSpan expiry);\n    void Set\u003cTResult, TValue\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression, TValue value, TimeSpan expiry);\n    Task SetAsync\u003cTResult, TValue\u003e(Expression\u003cFunc\u003cTResult\u003e\u003e expression, TValue value, TimeSpan expiry);\n    Task SetAsync\u003cTResult, TValue\u003e(Expression\u003cFunc\u003cTask\u003cTResult\u003e\u003e\u003e expression, TValue value, TimeSpan expiry);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaune8d%2Fexpressioncache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaune8d%2Fexpressioncache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaune8d%2Fexpressioncache/lists"}