gpt4 book ai didi

.net - 以Func体参数唯一标识匿名方法

转载 作者:行者123 更新时间:2023-12-01 05:29:01 25 4
gpt4 key购买 nike

我正在尝试编写一些神奇的代码来处理可能可行也可能不可行的缓存。基本上,这个想法是让 CacheManager 类具有一个静态方法,该方法接受一个 Func 作为参数执行。在静态方法的主体中,它将能够执行该 Func 并使用缓存键缓存结果,该缓存键唯一标识所传递的 Func 的内部结构(具有 0 个或更多参数的匿名方法)。使用提供的相同参数对该静态方法的后续调用将产生相同的缓存键并返​​回缓存结果。

我需要一种方法来唯一标识传入的匿名函数。

编辑:一旦我调整了匿名函数语法,表达式就提供了答案。

我担心必须在运行时编译表达式对性能的影响。鉴于这是为了性能而支持缓存的尝试,编译花费大量时间是愚蠢的。有什么想法吗?

用于测试的基本存储库:

public class Product
{
public int ID { get; set; }
public string Name { get; set; }
}

public class ProductRepository
{
private List<Product> products { get; set; }

public ProductRepository()
{
products = new List<Product>() { new Product() { ID = 1, Name = "Blue Lightsaber" }, new Product() { ID = 2, Name = "Green Lightsaber" }, new Product() { ID = 3, Name = "Red Lightsaber" } };
}

public Product GetByID(int productID)
{
return products.SingleOrDefault(p => p.ID == productID);
}
}

缓存管理器:

public class CacheManager
{
public static TResult Get<TResult>(Expression<Func<TResult>> factory)
{
if (factory == null) throw new ArgumentNullException("factory");

var methodCallExpression = factory.Body as MethodCallExpression;
if (methodCallExpression == null) throw new ArgumentException("factory must contain a single MethodCallExpression.");

string cacheKey = "|Repository:" + methodCallExpression.Method.DeclaringType.FullName + "|Method:" + methodCallExpression.Method.Name + "|Args";
foreach (var arg in methodCallExpression.Arguments)
{
cacheKey += ":" + (arg is ConstantExpression ? ((ConstantExpression)arg).Value : Expression.Lambda(arg).Compile().DynamicInvoke());
}

if (HttpContext.Current.Cache[cacheKey] == null)
{
HttpContext.Current.Cache[cacheKey] = factory.Compile().Invoke();
}
return (TResult)HttpContext.Current.Cache[cacheKey];
}
}

用法:

ProductRepository productRepository = new ProductRepository();
int productID = 1;
Product product;

// From repo
product = CacheManager.Get<Product>(() => productRepository.GetByID(1));

// From cache
product = CacheManager.Get<Product>(() => productRepository.GetByID(productID));

最佳答案

看起来您想做类似 Memoization 的事情. Memoization 是一种存储已计算结果的方法,这似乎是您的要求。

更好的方法是创建一个不同于原始对象的新函数对象,它将结果存储在字典中并对提供的参数执行查找。这个新函数将处理缓存,并在未命中时添加到缓存中。

此类将创建一个参数的函数的内存版本:

public static class memofactory
{
public static Func<In, Out> Memoize<In, Out>(Func<In, Out> BaseFunction)
{
Dictionary<In,Out> ResultsDictionary = new Dictionary<In, Out>();

return Input =>
{
Out rval;
try
{
rval = ResultsDictionary[Input];
Console.WriteLine("Cache hit"); // tracing message
}
catch (KeyNotFoundException)
{
Console.WriteLine("Cache miss"); // tracing message
rval = BaseFunction(Input);
ResultsDictionary[Input] = rval;
}
return rval;
};
}
}

根据您的示例,用法是:

        ProductRepository productRepository = new ProductRepository();
int productID = 1;
Product product;

Func<int, Product> MemoizedGetById = memofactory.Memoize<int, Product>(productRepository.GetByID);

// From repo
product = MemoizedGetById(1);

// From cache
product = MemoizedGetById(productID);

关于.net - 以Func体参数唯一标识匿名方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14334967/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com