2

我手头有一个 Windows 窗体应用程序,其中 GUI 和业务逻辑明确分离。解决方案很大(40 个项目,数千个类,大约 2000 个数据库表)。我的任务是找到如何重用业务逻辑来构建 Web 应用程序作为前端的解决方案。

我认为主要问题是我们的静态 Session 类,解决方案中的所有其他类都使用它:

public static class Session
{
    public static string CurrentUser { get; set; }

    public static string CurrentDatabase { get; set; }

    public static string CurrentCompanyProfile { get; set; }

    public static string CurrentLanguage { get; set; }
}

这个类在 ASP.NET 中不起作用,它将由所有用户共享,我无法替换它,因为它被大量使用。

我在想我需要从这个类中删除所有信息并只保留界面。通过调用属性代码的 get 方法会以某种方式将此调用重定向到 HttpContext.Current.Session 我将在其中存储一个包含所有这些信息的类。

考虑到 Session 驻留在不会引用 System.Web 的程序集中,并且考虑到我不能破坏我们的 WinForms 实现,我不确定如何正确执行此操作。

谢谢。

4

2 回答 2

2

假设您可以更新 Session 类,您可以抽象 Session 类中的属性存储。在您当前的应用程序中,您可以创建一个简单的内存存储,而在 Web 应用程序中,您可以创建一个 Web 会话存储。

首先定义一个 session-value-provider,你在当前的静态 Session 类中使用它。

public interface ISessionValueProvider {
    string CurrentUser { get; set; }
    string CurrentDatabase { get; set; }
    string CurrentCompanyProfile { get; set; }
    string CurrentLanguage { get; set; }
}

public static class Session {
    private static ISessionValueProvider _sessionValueProvider;
    public static void SetSessionValueProvider(ISessionValueProvider provider) {
        _sessionValueProvider = provider;
    }

    public static string CurrentUser { 
        get { return _sessionValueProvider.CurrentUser; } 
        set { _sessionValueProvider.CurrentUser = value; } 
    }
    // Etc for the other props
}

对于您当前的应用程序,定义一个使用内存来存储值的会话值提供程序。

public class MemorySessionValueProvider: ISessionValueProvider {
    public string CurrentUser {get; set; }
    // Etc for the other props
}

要使用它,请创建一个实例并将其提供给静态会话类。例如,您可以将其添加到您的 Main 方法中。

Session.SetSessionValueProvider(new MemorySessionValueProvider());

现在为您的 Web 应用程序创建一个使用 Web 会话的会话值提供程序。

public class WebSessionValueProvider: ISessionValueProvider {
    private const string CURRENTUSERKEY = "CurrentUser"; // TODO: Change this if necessary
    public string CurrentUser {
        get { return (string)HttpContext.Current.Session[CURRENTUSERKEY]; }
        set { HttpContext.Current.Session[CURRENTUSERKEY] = value; }
    }

    // Etc for the other props
}

再次,将这个 web-session-value-provider 的实例提供给静态会话类。例如,在 global.asax 中。

Session.SetSessionValueProvider(new WebSessionValueProvider);
于 2013-08-02T08:57:35.947 回答
1

我会为此使用IoC容器(例如Castle Windsor)。声明一个接口,例如IStateManager

public interface IStateManager
{
    T GetItem<T>(string key);
    SetItem<T>(string key, T value);
}

然后,您的Session类的实现将更改如下:

public static class Session
{
    private static IStateManager _manager;

    private static IStateManager Manager
    {
        get
        {
            if (_manager == null)
            {
                IStateManager m = null; // Get instance using IoC container
                Interlocked.CompareExchange(ref _manager, m, null);
            }

            return _manager;
        }
    }

    public static string CurrentUser
    {
        get { return Manager.GetItem<string>("CurrentUser"); }
        set { Manager.SetItem<string>("CurrentUser", value); }
    }

    // The rest is similar
}

对于 WinForms,实现将只在静态实例上运行,对于 ASP.NET,您将有一个不同的实现来维护会话中的数据。好处是您将只为不同的环境提供不同的安装程序,并且您的代码根本不需要了解它们(因此,逻辑将不依赖于 WinForms 或 ASP.NET)。

此外,这种方法是可测试的(例如,很容易模拟IStateManager使用Moq)。

于 2013-08-02T08:37:40.883 回答