带有参数的泛型/委派和传递函数

本文关键字:委派 传递函数 泛型 参数 | 更新日期: 2023-09-27 17:59:47

我正在尝试创建一个通用的CacheManager,我可以在整个应用程序中使用它,它将确保以一致的方式完成缓存项的所有管理,并遵守一些缓存访问模式。这将用于根据需要缓存所有类型的对象。

我知道我可以使用委托将函数传递给方法,您可以在下面看到。

public static T GetGlobalCacheitem( Func<int ,int , T> populateCacheCall )
        {
            string cacheKey = "test";
            var cachedObject = CacheFactory<T>.GlobalCache.GetGlobalCacheItem(cacheKey);
            if (cachedObject == null)
            {
                cachedObject =  populateCacheCall();
                CacheFactory<T>.GlobalCache.AddGlobalCacheItem(cachedObject, cacheKey);
            }
            return cachedObject;
        }

但是我有两个问题。

  1. 我想传递来填充缓存的大多数函数本身都有它们需要的参数。与上面的例子一样,这是一个将使用两个int参数的方法。第一个问题是,我如何也传递我希望调用函数的参数,因为它们在这个缓存处理程序中是不知道的,而在这个处理程序之外是已知的。AL所以这与下一个问题2有关,我如何才能在一种方法中做到这一点,无论函数需要多少参数(如果有的话)

  2. 第二个问题是,我需要传递来填充缓存项的许多函数都是不同的,因为有些函数没有参数,有些函数有一个,有些函数可能有多个,每个参数的类型都会不同。那么,我该如何在不必定义一个具有所有可能签名的函数的情况下实现这一点呢?该签名将涵盖付费使用的每一个可能的函数组合。

带有参数的泛型/委派和传递函数

如果函数的参数将在GetGlobalCacheitem方法之外填充,则可以用另一个委托欺骗调用函数,如下所示:

public static T GetGlobalCacheitem<T>(Func<T> populateCacheCall)

并称之为

Func<int ,int , object> tempPopulateCacheCall=(a,b)=>new object();
GetGlobalCacheitem(()=>tempPopulateCacheCall(1,2))

或具有不同参数的任何其他函数签名

Func<int , object> tempPopulateCacheCall=(a)=>new object();
GetGlobalCacheitem(()=>tempPopulateCacheCall(1))

您可以创建一个类,该类将封装函数参数,以便您能够在没有任何参数的情况下从此类实例调用此函数。这些参数的参数将被放入构造函数中:

interface ICachedFunction<out T>
{
    T Invoke();
}
class CustomFunctionWithVariousParameters<T> : ICachedFunction<T>
{
    private readonly Func<int, string, T> _function;
    private readonly int _parameter1;
    private readonly string _parameter2;
    public CustomFunctionWithVariousParameters(int parameter1, string parameter2, Func<int, string, T> function)
    {
        _function = function;
        _parameter1 = parameter1;
        _parameter2 = parameter2;
    }
    public T Invoke()
    {
        return _function(_parameter1, _parameter2);
    }
}

现在你可以在你的方法中使用这个解决方案:

public static T GetGlobalCacheitem( ICachedFunction<T> populateCacheCall )

希望这种方法会有所帮助。

您可以传递List<P>参数作为第一个参数,也可以使用Tuple<P>作为参数。

还尝试从函数和参数的哈希代码中生成全局缓存键。

如果我理解正确,您可能会在Dapper SqlMapper Identity函数中找到一些代码

我认为Reza Arab提出的结构很好,因为它符合你心目中的结构。然而,在我看来,拥有全局缓存是不可取的,尤其是因为它会使有效的垃圾收集变得困难(除非你对缓存的对象使用弱引用。但重复创建和删除的对象呢?在这种情况下,弱引用将禁止有效的缓存)。