1

我有一个 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 被“记住”并且只在创建链中确定一次?

我知道我可以重构并创建一个结构映射可以构造和缓存的 ILogin 接口/具体 - 但我希望我的各个层只关心一个简单的 int LoginID。

4

1 回答 1

3

尽管在服务中注入原始配置值是可以的,但是当您重复地将相同的原始配置注入到多个服务中时,您就缺少了抽象。

您的配置显然就是这种情况;你缺少一个抽象。

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

public interface ICurrentUser
{
    int LoginID { get; }
}

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

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

    public int LoginID { get; private set; }
}

这意味着您将不得不更改、和的构造函数CacheOrder,但是当您这样做时,您的配置变得更易于维护:CacheProductSQLOrderSQLProduct

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

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

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

Structure Map 中的默认生命周期是每个请求(每个对象图),因此相同的实例被注入到单个对象图中的所有对象中。

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

于 2013-05-21T11:30:25.920 回答