MethodInfo.Invoke有时会返回null,有时会返回值

时间:2009-08-21 09:39:12

标签: c# asp.net-mvc reflection multithreading methodinfo

我正在开发一个asp.net MVC应用程序。

我有一个包装存储库的类,该存储库使用简单的linq语句从数据库中获取数据。我编写了一个装饰器类来添加缓存逻辑(使用缓存应用程序块)。

因为我想要装饰几个方法,并且每个方法的逻辑都是相同的(检查是否存在于缓存中,如果没有调用真正的getter并存储在缓存中),我写了这样的东西:

一个辅助方法,它执行检查缓存中是否存在的常用逻辑,等等:

    public object CachedMethodCall(MethodInfo realMethod, params object[] realMethodParams)
    {
        object result = null;
        string cacheKey = CachingHelper.GenereateCacheKey(realMethod, realMethodParams);

        // check if cache contains key, if yes take data from cache, else invoke real service and cache it for future use.
        if (_CacheManager.Contains(cacheKey))
        {
            result = _CacheManager.GetData(cacheKey);
        }
        else
        {
            result = realMethod.Invoke(_RealService, realMethodParams);

            // TODO: currently cache expiration is set to 5 minutes. should be set according to the real data expiration setting.
            AbsoluteTime expirationTime = new AbsoluteTime(DateTime.Now.AddMinutes(5));
            _CacheManager.Add(cacheKey, result, CacheItemPriority.Normal, null, expirationTime);
        }

        return result;
    }

这一切都很好,很可爱。在每个装饰方法中,我有以下代码:

StackTrace currentStack = new StackTrace();
string currentMethodName = currentStack.GetFrame(0).GetMethod().Name;
var result = (GeoArea)CachedMethodCall(_RealService.GetType().GetMethod(currentMethodName), someInputParam);
return result;

问题是有时realMethod.Invoke(...)发生的行返回null。如果我在之后放置断点然后将执行返回到该行,则结果不为null并且从数据库中获取数据。所有输入变量都是正确的,数据存在于DB中,第二次运行获取数据,那么第一次运行出了什么问题?!

谢谢:)

1 个答案:

答案 0 :(得分:0)

我认为我设法通过更新代码解决了这个问题,如下所示:

    public object CachedMethodCall(MethodInfo realMethod, params object[] realMethodParams)
    {
        string cacheKey = CachingHelper.GenereateCacheKey(realMethod, realMethodParams);

        object result = _CacheManager.GetData(cacheKey);

        if (result == null)
        {
            result = realMethod.Invoke(_RealService, BindingFlags.InvokeMethod, null, realMethodParams, CultureInfo.InvariantCulture);

            // TODO: currently cache expiration is set to 5 minutes. should be set according to the real data expiration setting.
            AbsoluteTime expirationTime = new AbsoluteTime(DateTime.Now.AddMinutes(5));
            _CacheManager.Add(cacheKey, result, CacheItemPriority.Normal, null, expirationTime);
        }

        return result;
    }

我注意到,即使缓存不包含数据,之前的_CacheManager.Contains调用有时也会返回true。我怀疑线程导致了问题,但我不确定......