{"id":13629129,"url":"https://github.com/jeppevammenkristensen/cachesourcegenerator","last_synced_at":"2026-01-17T00:05:43.212Z","repository":{"id":207270153,"uuid":"718848600","full_name":"jeppevammenkristensen/cachesourcegenerator","owner":"jeppevammenkristensen","description":"A source generator that can generate simple cache boilerplate around a method","archived":false,"fork":false,"pushed_at":"2024-04-19T22:59:57.000Z","size":163,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-08T09:49:19.066Z","etag":null,"topics":["cache","csharp","csharp-sourcegenerator","dotnet","generator","memorycache","roslyn","source","sourcegenerator"],"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/jeppevammenkristensen.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-14T23:08:03.000Z","updated_at":"2024-10-12T17:53:00.000Z","dependencies_parsed_at":"2024-04-10T18:03:36.214Z","dependency_job_id":"c5b61bd5-931d-437e-ad73-668c39f74497","html_url":"https://github.com/jeppevammenkristensen/cachesourcegenerator","commit_stats":null,"previous_names":["jeppevammenkristensen/cachesourcegenerator"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeppevammenkristensen%2Fcachesourcegenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeppevammenkristensen%2Fcachesourcegenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeppevammenkristensen%2Fcachesourcegenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeppevammenkristensen%2Fcachesourcegenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeppevammenkristensen","download_url":"https://codeload.github.com/jeppevammenkristensen/cachesourcegenerator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249316056,"owners_count":21249885,"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","csharp-sourcegenerator","dotnet","generator","memorycache","roslyn","source","sourcegenerator"],"created_at":"2024-08-01T22:01:02.952Z","updated_at":"2025-04-17T04:33:03.536Z","avatar_url":"https://github.com/jeppevammenkristensen.png","language":"C#","funding_links":[],"categories":["Content","Source Generators"],"sub_categories":["111. [cachesourcegenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/cachesourcegenerator) , in the [FunctionalProgramming](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#functionalprogramming) category","Other"],"readme":"# Cache source generator\n _[![CacheSourceGenerator Nuget Version](https://img.shields.io/nuget/v/CacheSourceGenerator?style=flat-square\u0026label=NuGet%3A%20CacheSourceGenerator)](https://www.nuget.org/packages/CacheSourceGenerator)_\n\n*Important* `CachoAttribute` has been renamed to `GenerateMemoryCacheAttribute` \n\nA source generator that can generate simple cache boilerplate to wrap around a method\n\n## Getting started\n\nThis generator works by wrapping a method in another method with the same signature, that ensures calls are cached.\n\nIn a partial class decorate the method with the `GenerateMemoryCache` attribute\n\n```csharp\npublic partial class SampleEntity\n{\n    private readonly IMemoryCache _memoryCache;\n\n    public SampleEntity(IMemoryCache memoryCache)\n    {\n        _memoryCache = memoryCache;\n    }\n\n    [GenerateMemoryCache(MethodName = \"GetId\", CacheEnricherProcessor = nameof(ProcessCacheEntry))]\n    private string? DoGetSomeValue(int id)\n    {\n        return \"Someresult\";\n    }\n\n    \n    public void ProcessCacheEntry(ICacheEntry entry)\n    {\n        entry.SlidingExpiration = TimeSpan.FromMinutes(2);\n    }\n}\n```\n\nAnd it will generate\n\n```csharp\npublic partial class SampleEntity\n{\n    public string? GetId(int id)\n    {\n        var _key_ = new\n        {\n            _MethodName = \"DoGetSomeValue\",\n            _ClassName = \"SampleEntity\",\n            id\n        };\n        IMemoryCache _cache_ = _memoryCache;\n        return _cache_.GetOrCreate(_key_, _entry_ =\u003e\n        {\n            ProcessCacheEntry(_entry_);\n            return DoGetSomeValue(id);\n        });\n    }\n    \n    public void GetId_Evict(int id)\n    {\n        var _key_ = new\n        {\n            _MethodName = \"DoGetSomeValue\",\n            _ClassName = \"SampleEntity\",\n            id\n        };\n        IMemoryCache _cache_ = _memoryCache;\n        _cache_.Remove(_key_);\n    }\n}\n```\n\nNote that that defining the CacheEnricherProcessor is optional and can be left out\n\n## Cache access\n\nThe IMemoryCache can be retrieved in two ways. Autogenerated or by providing it in the class\n\n### Autogenerated cache access code\n\nThis requires that you install the nuget package Microsoft.Extensions.Caching.Memory.\n\nDecorate a method that returns a value on a partial class with the GenerateMemoryCache Attribute\n\n```csharp\npublic partial class SomeClass\n{\n\n  [CacheSourceGenerator.Cache(MethodName = \"SomeMethod\")]\n  private string DoSomeMethod(string id, int age)\n  {\n      return $\"{id}{age}\";\n  }\n}\n```\n\nThis will generate the code below.\n\n```csharp\npublic partial class SomeClass\n{\n    private static class CacheInit\n    {\n        static CacheInit()\n        {\n            _memoryCache = new Lazy\u003cIMemoryCache\u003e(() =\u003e new MemoryCache(new MemoryCacheOptions()));\n        }\n\n        private static Lazy\u003cIMemoryCache\u003e _memoryCache;\n        public static IMemoryCache MemoryCache =\u003e _memoryCache.Value;\n    }\n\n    public string SomeMethod(string id, int age)\n    {\n        var key = new\n        {\n            _MethodName = \"DoSomeMethod\",\n            _ClassName = \"SomeClass\",\n            id,\n            age\n        };\n        IMemoryCache cache = CacheInit.MemoryCache;\n        return cache.GetOrCreate(key, entry =\u003e\n        {\n            return DoSomeMethod(id, age);\n        });\n    }\n}\n```\n\n### Providing the cache from the class\n\nAn alternative is to provide a IMemoryCache instance from the class. This can be done through a\n\n* Field\n* Property\n* Method (parameter less)\n\n```csharp\npublic static partial class SomeOtherClass\n{\n    private static IMemoryCache GetCache() =\u003e new MemoryCache(new MemoryCacheOptions());\n\n    [CacheSourceGenerator.GenerateMemoryCache(MethodName = \"SomeMethod\")]\n    public static Task\u003cstring\u003e ExecuteCall()\n    {\n        return Task.FromResult(\"Hello\");\n    }\n}\n```\n\nThis will generate the code below.\n\n```csharp\npublic static partial class SomeOtherClass\n{\n    public async static Task\u003cstring\u003e SomeMethod()\n    {\n        var key = new\n        {\n            _MethodName = \"ExecuteCall\",\n            _ClassName = \"SomeOtherClass\",\n        };\n        IMemoryCache cache = GetCache();\n        var result = await cache.GetOrCreateAsync(key, async entry =\u003e\n        {\n            return await ExecuteCall();\n        });\n        return result ?? throw new InvalidOperationException(\"Expected non empty result\");\n    }\n}\n```\n\n## Method generation\n\nif the method is async or returning a `Task\u003cT\u003e` the generated method will take that into consideration.\n\nIf the return type is not nullable, the generated method will throw an exception if the result of the method call is null.\n\n## GenerateMemoryCache Atrribute\n\n### MethodName\nThe GenerateMemoryCache needs to as a minimum have MethodName set as this is the desired method name of the generated method.\n\n### CacheEnricherProcessor\nIf you want to control the `ICacheEntry` object, you can use this property to point to a method that takes a `ICacheEntry` as input and\nreturns void or if async as Task. This method will be called like below and can be used set for instance expiration\n\n```csharp\nvar _result_ = _cache_.GetOrCreate(_key_, _entry_ =\u003e\n{\n    CacheEnricher(_entry_);\n    return DoGetName(id);\n});\n```\n\n### KeyGenerator\nOut of the box a key will be auto generated that will consist of \n\n* MethodName\n* ClassName\n* The parameters of the method\n\nIf you want to create a custom key, you can use the KeyGenerator property to point to a method that will generate the key. The method must match the parameters of the decorated method by type (it's okay if there is a mismatch between names)\n\nThe return type can be anything but void\n\nSo for \n\n```csharp\n[GenerateMemoryCache(KeyGenerator=nameof(GenerateKey), MethodName=\"SomeName\")]\npublic string Somemethod(string id, int number, bool boolValue)\n```\n\na valid KeyGenerator method could be\n\n```csharp\npublic (string id, int number, bool boolean) \n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeppevammenkristensen%2Fcachesourcegenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeppevammenkristensen%2Fcachesourcegenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeppevammenkristensen%2Fcachesourcegenerator/lists"}