你如何抽象页面会话属性?

时间:2015-02-13 20:20:50

标签: asp.net session dependency-injection webforms

我正在关注此example

示例代码:

public class Global : HttpApplication
{
    private Poster _posterDetails; 
    private Posting _postingDetails;
    private Property _propertyDetails;
    protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        if (HttpContext.Current.Session == null) return;
        _posterDetails = HttpContext.Current.Session["Poster"] as Poster;
        _postingDetails = HttpContext.Current.Session["Posting"] as Posting;
        _propertyDetails = HttpContext.Current.Session["Property"] as Property;
    }
}

这些会话变量遍布整个应用程序,我需要抽象它们的检索。说,以后我从db而不是当前会话中获取它们。

Session已加入PageContext。如何将该依赖项注入可能的当前属性getter的具体实现中。

2 个答案:

答案 0 :(得分:1)

围绕HttpContext创建一个抽象:

public interface IHttpContextFactory
{
    HttpContextBase Create();
}

public class HttpContextFactory
    : IHttpContextFactory
{
    public HttpContextBase Create()
    {
        return new HttpContextWrapper(HttpContext.Current);
    }
}

然后将其注入专门的服务以进行这些设置。

public interface ISettings
{
    T GetValue<T>(string key);
    void SetValue<T>(string key, T value);
}

public class ContextSettings
    : ISettings
{
    private readonly IHttpContextFactory httpContextFactory;
    private HttpContextBase context;

    public RequestCache(
        IHttpContextFactory httpContextFactory
        )
    {
        if (httpContextFactory == null)
            throw new ArgumentNullException("httpContextFactory");

        this.httpContextFactory = httpContextFactory;
    }

    protected HttpContextBase Context
    {
        get 
        {
            if (this.context == null)
            {
                this.context = this.httpContextFactory.Create();
            }
            return context;
        }
    }

    public virtual T GetValue<T>(string key)
    {
        if (this.Context.Session.Contains(key))
        {
            return (T)this.Context.Session[key];
        }
        return default(T);
    }

    public virtual void SetValue<T>(string key, T value)
    {
        this.Context.Session[key] = value;
    }
}

稍后可以通过实现ISettings并提供不同的构造函数依赖项来将服务替换为另一种存储机制。请注意,更改构造函数签名不需要不同的接口。

也就是说,您应该提供另一个服务(或者可能不止一个),它将ISettings作为依赖项,以便您可以创建显式属性。您应该致力于为特定目的提供集中的相关属性集。您的应用程序也不必知道属性的类型以便检索其值 - 它应该只调用隐藏这些细节的属性。

public class SomeSettingsService: ISomeSettingsService
{
    private readonly ISettings settings;

    public SomeSettingsService(ISettings settings)
    {
        if (settings == null)
            throw new ArgumentNullException("settings");
        this.settings = settings;
    }

    public Poster Poster
    {
        get { return this.settings.GetValue<Poster>("Poster"); }
        set { this.settings.SetValue<Poster>("Poster", value); }
    }

    public Posting Posting
    {
        get { return this.settings.GetValue<Posting>("Posting"); }
        set { this.settings.SetValue<Posting>("Posting", value); }
    }

    public Property Property
    {
        get { return this.settings.GetValue<Property>("Property"); }
        set { this.settings.SetValue<Property>("Property", value); }
    }
}

答案 1 :(得分:0)

不确定这是不是你问的问题......我经常做的是创建服务:

公共接口ISessionService {     object Get(string key);

void Save(string key, object value);

}

然后我实现了这个,调用HttpContext.Current.Session[key]并返回值。创建Get<T>(string key)以返回对象也不难。打破所有依赖关系以使用它(这是困难的部分)。

没有无缝的方法来破坏依赖性......它必须通过手动更改。