配置StructureMap以生成并“记住”构造函数param文字

时间:2013-05-20 15:25:02

标签: dependency-injection structuremap

我有一个类似于:

的StructureMap配置
cfg.For<ICacheOrder>().Use<CacheOrder>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ICacheProduct>().Use<CacheProduct>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ISQLOrder>().Use<SQLOrder>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ISQLProduct>().Use<SQLProduct>().Ctor<int>().Is(context => LoginHelper.LoginID);

通过构造函数注入,可以创建一个对象链,其中一些对象需要一个在创建时确定的int LoginID。静态LoginHelper确定LoginID。

目前在我的配置中,为每个创建的对象调用LoginHelper。有没有办法,也许是通过StructureMap的IContext,让LoginID成为&#34;记住&#34;并且只在创作链中确定一次?

我知道我可以重构并创建一个可以构造和缓存的ILogin接口/具体 - 但我更喜欢我的各个层只关注一个简​​单的int LoginID。

1 个答案:

答案 0 :(得分:3)

虽然可以在服务中注入原始配置值,但是当您将相同的原语重复注入多个服务时,您将缺少抽象。

您的配置显然就是这种情况;你错过了抽象。

解决方案是让这些服务依赖于抽象而不是原始值。例如:

public interface ICurrentUser
{
    int LoginID { get; }
}

您可以创建一个相当简单的实现,如下所示:

public class CurrentUserImpl : ICurrentUser
{
    public CurrentUserImpl()
    {
        this.LoginID = LoginHelper.LoginID;
    }

    public int LoginID { get; private set; }
}

这意味着您必须更改CacheOrderCacheProductSQLOrderSQLProduct的构造函数,但是当您执行此操作时,您的配置可以更加可维护:

cfg.For<ICacheOrder>().Use<CacheOrder>();
cfg.For<ICacheProduct>().Use<CacheProduct>();
cfg.For<ISQLOrder>().Use<SQLOrder>();
cfg.For<ISQLProduct>().Use<SQLProduct>();

“记住param文字”的问题现在立即消失,因为我们现在可以注册ICurrentUser如下:

cfg.For<ICurrentUser>().Use<CurrentUserImpl>();

结构图中的默认生命周期是每个请求(每个对象图),因此同一个实例将被注入单个对象图中的所有对象。

另一种选择是使用HttpContext生命周期注册它,但这当然只适用于运行ASP.NET Web应用程序。