如何使用 StructureMap 在 ASP.NET MVC 中为不同的上下文注入不同的实例?

How to inject different instance(s) for different context in ASP.NET MVC using StructureMap?

我们正在使用 类 从 Registry 继承来在我们的 ASP.NET MVC 4 应用程序启动中配置我们的 StructureMap 容器。

注册表之一的一些摘录-类:

For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeImplementation>();

我们希望根据上下文使用不同的接口实例。 (例如,从数据库 "online" 模式切换到 "maintenance" 模式,其中所有内容都保存在文件系统中;因此在我们的应用程序中到处使用其他接口(即存储库))

例如默认情况下它应该使用 SomeImplementation 但是当在 url 中传递某种查询字符串时(为了命名一个简单的 "context" 场景)它应该使用 SomeOtherImplementation.

如何实现多个 interfaces/types?

我们应该为此使用 named 实例吗?喜欢:

For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>().Named("other");

我阅读了有关 StructureMap Profiles 的信息,但我不确定这是否是正确的方法。 我们应该为此使用配置文件吗?比如:

Profile("other", profileExpression =>
  {
     For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>();
  });

我们如何即时切换不同的配置?

ObjectFactory.Container.SetDefaultsToProfile("other");

这边? (在 mvc 的哪个阶段 "life-cycle" 这最早会发生?)

这可以只是当前请求或当前用户会话的临时切换吗?

提前致谢!

根据我的经验,像这样的运行时配置最好使用 abstract factory 来实现,它负责在运行时创建您的依赖项。

然后可以像这样在 StructureMap 中注册此依赖项:

您的注册表:

public class StorageRegistry : Registry
{
    public StorageRegistry()
    {
        ...
        this.For<IDataStoreInstance>().Use(ctx => ctx.GetInstance<DataStoreAbstractFactory>().ConfigureStorage());
        ...
    }
}

现在您的 DataStoreAbstractFactory 负责根据您的配置创建和配置必要的存储实例。由于 DataStoreAbstractFactory 现在已在 StructureMap 中注册,您可以将必要的依赖项注入其中以确定要使用的存储方法。

实现示例:

public class DataStoreAbstractFactory
{
    public DataStoreAbstractFactory()
    {
        // Dependencies to figure out data storage method can be injected here.
    }

    public IDataStoreInstance ConfigureStorage()
    {
        // This method can be used to return type of storage based on your configuration (ie: online or maintenance)
    }
}

public interface IDataStoreInstance
{
    void Save();
}

public class DatabaseStorage : IDataStoreInstance
{
    public void Save()
    {
        // Implementation details of persisting data in a database
    }
}

public class FileStorage : IDataStoreInstance
{
    public void Save()
    {
        // Implementation details of persisting data in a file system
    }
}

用法:

您的 controller/services 或其他任何人现在完全不知道他们在访问和保存数据时使用的存储方法。

public class UpdateController : Controller
{
    public IDataStoreInstance StorageInstance { get; set; }

    public UpdateController(IDataStoreInstance storageInstance)
    {
        StorageInstance = storageInstance;
    }

    [HttpPost]
    public ActionResult Index()
    {
        ...

        this.StorageInstance.Save();

        ...
    }

    ...

}