注入 - AppFabric Cache的InSessionScope扩展问题

时间:2015-02-25 09:17:50

标签: c# asp.net-mvc ninject ninject.web.mvc ninject-extensions

Ninject没有为网站提供InSessionScope绑定,因此我们创建了自己的扩展:

public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
{
   return parent.InScope(SessionScopeCallback);
}

private const string _sessionKey = "Ninject Session Scope Sync Root";

private static object SessionScopeCallback(IContext context)
{
    if (HttpContext.Current.Session[_sessionKey] == null)
    {
        HttpContext.Current.Session[_sessionKey] = new object();
    }
    return HttpContext.Current.Session[_sessionKey];
}

此扩展程序正常工作,直到我们使用标准的本地SessionStore。

但是我们改变了SessionStore,现在我们使用“AppFabricCacheSessionStoreProvider”,这个商店不再是服务器上的本地机器了。

问题是Ninject试图解析一个被序列化和反序列化的对象的引用,它来自服务器而不是来自本地内存,所以ninject无法找到引用。结果是,ninjects始终创建一个新的Object,SessionScope不再起作用。

编辑1:

我们正在使用此功能

https://msdn.microsoft.com/en-us/library/hh361711%28v=azure.10%29.aspx

在这里我可以使用标准的“HttpContext.Current.Session”对象,列表内容存储在服务器上而不是本地机器上。

2 个答案:

答案 0 :(得分:0)

所以在架构上你有一个问题,你需要在某处存储AppFabric的设置,这是你的静态方法的问题。但假设您创建了一个公共静态类,如下所示:

public static class AppCache
{

    public static DataCache Cache { get; private set; }

    static AppCache()
    {
        List<DataCacheServerEndpoint> servers = new List<DataCacheServerEndpoint>(1);

        servers.Add(new DataCacheServerEndpoint("ServerName", 22233)); //22233 is the default port

        DataCacheFactoryConfiguration configuration = new DataCacheFactoryConfiguration
        {
            Servers = servers,
            LocalCacheProperties = new DataCacheLocalCacheProperties(),
            SecurityProperties = new DataCacheSecurity(),
            RequestTimeout = new TimeSpan(0, 0, 300),
            MaxConnectionsToServer = 10,
            ChannelOpenTimeout = new TimeSpan(0, 0, 300),
            TransportProperties = new DataCacheTransportProperties() { MaxBufferSize = int.MaxValue, MaxBufferPoolSize = long.MaxValue }
        };

        DataCacheClientLogManager.ChangeLogLevel(System.Diagnostics.TraceLevel.Off);

        var _factory = new DataCacheFactory(configuration);

        Cache = _factory.GetCache("MyCache");
    }
}

然后您可以像这样更改扩展名:

public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
{
   return parent.InScope(SessionScopeCallback);
}

private const string _sessionKey = "Ninject Session Scope Sync Root";

private static object SessionScopeCallback(IContext context)
{
    var cachedItem = AppCache.Cache.Get("MyItem"); // IMPORTANT: For concurrency reason, get the whole item down to method scope.
    if (cachedItem  == null)
    {
        cachedItem = new object();
        AppCache.Cache.Put("MyItem", cachedItem);
    }
    return cachedItem;
}

答案 1 :(得分:0)

我找到了一个&#34;解决方案&#34;到目前为止它的工作并不完美,因为我正在避免AppFabric商店使用Localstore作为对象参考。

    public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
    {
       return parent.InScope(SessionScopeCallback);
    }

    public static Dictionary<string, object> LocalSessionStore = new Dictionary<string, object>();

    private const string _sessionKey = "Ninject Session Scope Sync Root";

    private static object SessionScopeCallback(IContext context)
    {
        var obj = new object();
        var key = (string)HttpContext.Current.Session[_sessionKey];

        if (string.IsNullOrEmpty(key))
        {
            var guid = Guid.NewGuid().ToString();
            HttpContext.Current.Session[_sessionKey] = guid;
            LocalSessionStore.Add(guid, obj);
        }
        else if(!LocalSessionStore.ContainsKey(key))
        {
            LocalSessionStore.Add(key, obj);
            return LocalSessionStore[key];
        }
        else if (LocalSessionStore.ContainsKey(key))
        {
            return LocalSessionStore[key];
        }

        return HttpContext.Current.Session[_sessionKey];
    }
}