代码之家  ›  专栏  ›  技术社区  ›  Omar

应用程序服务层作为静态类

  •  9
  • Omar  · 技术社区  · 15 年前

    在我的ASP.NET MVC应用程序中,我有一个包含所有业务逻辑/服务层的项目。此项目与位于单独项目中的数据库(实体框架)交互。

    我希望能够轻松地访问服务层,所以我在其中创建了静态类,以便可以轻松地引用它们。例如,如果我在控制器中,需要创建一个新帐户:

     ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc..
    

    然后,服务层执行所有必需的逻辑,然后通过 DatabaseLayer .

        private static AllRepos _Repos;
        private static AllRepos Repos { 
           get 
            { 
               if(_Repos == null)
                  _Repos = new AllRepos();
    
               return _Repos
            }
        }
    
        public static void CreateAccount(string username, password)
        {
            string salt = GenerateSalt();
            Account newAccount = DatabaseLayer.Models.Account
                  { 
                  Name = username,
                  Password = HashPassword(password, salt),
                  Salt = salt
                  };
            Repos.AddAccount(newAccount);      
        }
    

    因为我不想在我的服务层的任何地方执行以下操作:

     AccountRepository Accounts = new DatabaseLayer.AccountRepository();
    

    相反,我为我的存储库创建了一个包装类,这样我只需要实例化一次就可以使用所有其他存储库。

     public class AllRepos
     {
    
        private AccountRepository _Accounts;
    
        public AccountRepository Accounts
        {
            get
            {
                if (_Accounts== null)
                    _Accounts= new AccountRepository();
    
                return _Accounts;
            }
        }
    
        // the same is done for every other repository (currently have about 10+)
      }
    

    在服务层的静态类中使用。

    因为我所有的服务层类都是静态的, Repos 字段也是静态的,我经常遇到的一个明显问题是,从多个数据上下文中检索同一个对象会导致更新/删除时出现奇怪的行为。

    我理解,如果我像在应用程序生命周期中使用静态成员/类那样使用它们,这是可以预料的,但是有没有一种方法能够将服务层用作 ServiceLayer.Accounts.Method() 不必创建一个非静态类,该类需要在使用它的任何地方进行实例化,并且不会由于多个DataContext实例而遇到CRUD问题?

    4 回复  |  直到 14 年前
        1
  •  15
  •   womp    15 年前

    你的方法确实不是推荐的。就我个人而言,我决不会允许我的团队采用这种方法。缺点:

    1. 您所遇到的主要线程问题并不容易解决。
    2. 你根本不能轻易地测试这个。
    3. 数据访问的不切实际抽象

    创建存储库实例的最大原因是,如果需要,可以注入依赖项。对此最著名的论点是单元测试,这样您就可以模拟依赖关系,但我已经构建了许多存储库,它们的接口依赖关系会在生产代码中发生更改。

    无论如何,您应该只是将存储库实例化作为基本服务类的一部分。没有理由它必须是“静态的” 实例调用无处不在”。在基类中应该有有限的实例实例化代码。

        2
  •  10
  •   Craig Stuntz    15 年前

    我不知道你为什么如此坚决地反对使用实例。除了您现在拥有的代码不必要地复杂之外,使用静态类型还使得单元测试更加困难。静态类型类似于单例类型,您不能模拟/替换它。在我看来,您真正的问题可能是,“我如何终身管理我的服务层实例?”通常,通过每个Web请求有一个实例来实现这一点。在ASP.NET MVC应用程序中,可以 new up a DI container via a ControllerFactory, and handle all of this. [PDF]

        3
  •  1
  •   Luhmann    15 年前

    您需要以一种深思熟虑的方式处理ObjectContext的范围,比如 Unit Of Work pattern

    除此之外,我认为您应该重新考虑做所有静态的事情,正如Womp所说,您得到了非常高的耦合,并且使测试变得非常困难,并且您可以通过使用IOC容器在管理依赖关系图方面获得很多帮助。

    我可以这么说,我以前做过那种事,把自己烧死了。)

        4
  •  -3
  •   Ahmad    15 年前

    单件(和如前所述的静态类)是邪恶的,应该不惜一切代价避免,特别是在Web应用程序中。

    推荐文章