且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用StructureMap注入在ASP.NET MVC为不同的环境不同的实例(S)?

更新时间:2023-02-10 08:09:36

从我的经验,这样的运行时配置是使用的抽象工厂,负责在运行时创建的依赖。

这依赖可再与StructureMap登记,像这样:

您的注册表:

 公共类StorageRegistry:注册表
{
    公共StorageRegistry()
    {
        ...
        this.For< IDataStoreInstance方式>()使用(CTX => ctx.GetInstance< D​​ataStoreAbstractFactory>()ConfigureStorage());
        ...
    }
}

现在你的 DataStoreAbstractFactory 负责创建和配置的基础上配置必要的存储实例。由于 DataStoreAbstractFactory 现在与StructureMap注册你能注入必要的依赖将它确定要使用的存储方法。

实施例如:

 公共类DataStoreAbstractFactory
{
    公共DataStoreAbstractFactory()
    {
        //依赖弄清楚数据存储方法可以在这里注射。
    }    公共IDataStoreInstance ConfigureStorage()
    {
        //此方法可用于返回根据您的配置存储的类型(如:在线或维护)
    }
}公共接口IDataStoreInstance
{
    无效保存();
}公共类DatabaseStorage:IDataStoreInstance
{
    公共无效保存()
    {
        在数据库中的持久数据//实施细节
    }
}公共类FileStorage:IDataStoreInstance
{
    公共无效保存()
    {
        在一个文件系统中持续的数据//实施细节
    }
}

用法:

您控制器/服务或任何现在完全不知道他们正在使用访问和持久化数据什么时候存储方法。

 公共类UpdateController:控制器
{
    公共IDataStoreInstance StorageInstance {搞定;组; }    公共UpdateController(IDataStoreInstance storageInstance)
    {
        StorageInstance = storageInstance;
    }    [HttpPost]
    公众的ActionResult指数()
    {
        ...        this.StorageInstance.Save();        ...
    }    ...}

We are using classes inheriting from Registry to configure our StructureMap container in our ASP.NET MVC 4 application startup.

Some excerpt from one of the registry-classes:

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

We would like use different instances of our interfaces depending on the context. (For example switching from database "online" mode to "maintenance" mode where everything is saved on filesystem; therefore using other interfaces (i.e. repositories) all over the place in our application)

For example by default it should use SomeImplementation but when passing some kind of querystring in the url (to name a simple "context" scenario) it should use SomeOtherImplementation.

How can this be achieved for multiple interfaces/types?

Should we use named instances for this? Like:

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

I read about StructureMap Profiles but i'm not sure if this is the right way to go. Should we use profiles for this? Like i.e.:

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

How can we switch different configurations on the fly?

ObjectFactory.Container.SetDefaultsToProfile("other");

This way? (At what stage in mvc "life-cycle" this can happen at the earliest?)

Can this be a temporary switch for just the current request or current users session?

Thanks in advance!

From my experience, runtime configuration like this is best achieved using an abstract factory that is responsible for creating your dependency during runtime.

This dependency can then be registered with StructureMap like so:

Your registry:

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

Now your DataStoreAbstractFactory is responsible for creating and configure the necessary storage instance based on your configuration. As DataStoreAbstractFactory is now registered with StructureMap you're able to inject the necessary dependencies into it for determining which storage method to use.

Implementation example:

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
    }
}

Usage:

Your controller/services or whatever are now completely unaware of what storage method they're using when accessing and persisting data.

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

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

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

        this.StorageInstance.Save();

        ...
    }

    ...

}