IoC - 在构造函数中初始化对象状态

时间:2016-04-03 17:00:38

标签: c# ioc-container

对于每个页面请求,我需要从数据库中获取一些当前用户权限数据,然后在逻辑中多次使用此信息 (由几个对象组成)

我希望每次请求从数据库中获取一次数据,并在需要时通过注入来重用它。

以下是最好的方法吗?

1)定义一个像这样的对象

class ApplicationUser : IApplicationUserProvider
{
    private UserPermissions _userPermissions;
    ...

    public ApplicationUser(IDatabase userService)
    {
        _userPermissions = userService.GetUserPermission(); // this would executed for every request once
    }

    UserRoles GetRoles()
    {
        return _userPermissions;
    }
}

2)定义类似这样的ioc

 var container1 = new Container(c =>
            {
        c.For<IDatabase>().Use<Database>();
        c.For<IApplicationUser>().Use<ApplicationUser >();
        c.For<IApplicationLogic1>().Use<ApplicationLogic1>(); // this has IApplicationUser in ctor
        c.For<IApplicationLogic2>().Use<ApplicationLogic2>(); // this has IApplicationUser in ctor
            }); 

3)控制器将是

void PageController(IApplicationLogic1 l1)
{
    l1.Process();
    l2.Process();   
}

1 个答案:

答案 0 :(得分:2)

UserPermissions信息是运行时数据,正如here所解释的那样,在构造对象图时不应注入或解析运行时数据。

相反,对userService.GetUserPermission()的调用应该移出构造函数。例如,通过使用Lazy<T>来延迟呼叫:

class ApplicationUser : IApplicationUserProvider
{
    private Lazy<UserPermissions> _userPermissions;

    public ApplicationUser(IDatabase userService) {
        _userPermissions = new Lazy<UserPermissions>(userService.GetUserPermission);
    }

    UserRoles GetRoles() {
        return _userPermissions.Value.GetRoles();
    }
}

另一种选择是在IDatabase上定义一个将实现缓存的装饰器:

public class PerRequestCacheDatabaseDecorator : IDatabase
{
    private IDatabase _decoratee;

    public PerRequestCacheDatabaseDecorator(IDatabase decoratee) {
        _decoratee = decoratee;
    }

    public UserPermissions GetUserPermission() {
        var items = HttpContext.Current.Items;
        if (items["permissions"] == null)
            items["permissions"] = _decoratee.GetUserPermission();
        return (UserPermissions)items["permissions"];
    }
}

通过将真实数据库包装在PerRequestCacheDatabaseDecorator中,您可以将ApplicationUser简化为以下内容:

class ApplicationUser : IApplicationUserProvider
{
    private IDatabase _userService;

    public ApplicationUser(IDatabase userService) {
        _userService = userService;
    }

    public UserRoles GetRoles() {
        return _userService.GetUserPermission().GetRoles();
    }
}

现在,ApplicationUserDatabase类都不关心这种性能优化,这是一件好事。装饰器允许我们插入此性能优化,而无需更改任何现有类。