Asp.net mvc 5 在MVC5控制器中使用StructureMap[4.7.0]Setter注入

Asp.net mvc 5 在MVC5控制器中使用StructureMap[4.7.0]Setter注入,asp.net-mvc-5,inversion-of-control,structuremap,structuremap4,setter-injection,Asp.net Mvc 5,Inversion Of Control,Structuremap,Structuremap4,Setter Injection,我正在尝试将iaapplicationconfigurationsection实现注入这个MVC5控制器,这样我就可以从我所有视图中的web.config自定义部分访问一些信息(各种字符串): public class BaseController : Controller { public IApplicationConfigurationSection AppConfig { get; set; } public BaseController() {

我正在尝试将
iaapplicationconfigurationsection
实现注入这个MVC5
控制器
,这样我就可以从我所有视图中的
web.config
自定义部分访问一些信息(各种字符串):

public class BaseController : Controller
{
    public IApplicationConfigurationSection AppConfig { get; set; }

    public BaseController()
    {
        ViewBag.AppConfig = AppConfig; // AppConfig is always null
    }
}
我想使用setter注入,这样我就不必把派生的
控制器
构造函数与它们并不真正关心的参数混在一起

注意:如果有更好的方法注入基类依赖项,请告诉我。我承认我在这方面可能走得不对

在my
Global.asax
中,我加载我的StructureMap配置:

private static IContainer _container;

protected void Application_Start()
{
    _container = new Container();

    StructureMapConfig.Configure(_container, () => Container ?? _container);
    // redacted other registrations
}
My
StructureMappConfig
类加载我的注册表:

public class StructureMapConfig
{
    public static void Configure(IContainer container, Func<IContainer> func)
    {
        DependencyResolver.SetResolver(new StructureMapDependencyResolver(func));

        container.Configure(cfg =>
        {
            cfg.AddRegistries(new Registry[]
            {
                new MvcRegistry(),
                // other registries redacted
            });
        });
    }
}
这会起作用,但没有


我发现,如果我放弃setter注入而使用构造函数注入,它就会像广告中那样工作。我仍然想知道我错在哪里,但我想强调的是,我不是StructureMap大师-可能有更好的方法避免构造函数注入我的基类依赖项。如果你知道我应该怎么做,但我不是,请分享

而在这种情况下,构造函数注入似乎是解决所述问题的更好方法,如下所示

方法和类应该明确地要求(通常通过方法参数或构造函数参数)它们需要的任何协作对象才能正常工作

在您的视图中提到只需要访问
AppConfig
,这让我觉得这更像是一个跨领域的问题

控制器本身似乎不需要使用依赖项,因此不需要显式地将它们注入控制器,以便视图可以使用依赖项

考虑使用一个动作过滤器,该过滤器可以解决依赖关系,并在请求通过管道时通过相同的
ViewBag
使视图可以使用该过滤器

公共类访问应用程序配置属性:ActionFilterAttribute{
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext){
var resolver=DependencyResolver.Current;
var appConfig=(iaapplicationconfigurationsection)resolver.GetService(typeof(iaapplicationconfigurationsection));
filterContext.Controller.ViewBag.AppConfig=AppConfig;
}
}
现在,这使得视图可以使用所需的信息,而不需要使用控制器的紧密耦合。不再需要将依赖项注入派生类

通过使用过滤器属性修饰控制器/操作

[AccessAppConfig]//可用于其所有操作
公共类HomeController:控制器{
//[AccessAppConfig]//如果要隔离到单个操作/视图,请直接使用
公共行动结果索引(){
//...
返回视图();
}
}
或全局用于所有请求

公共类过滤器配置{
公共静态无效注册表全局过滤器(全局过滤器集合过滤器){
添加(新的accessAppConfigAttribute());
}
}

在这一点上,使用哪个IoC容器并不重要。一旦配置了依赖项解析程序,视图应该可以访问
ViewBag

中所需的信息,构造函数注入是更好的方法。我本来打算回答这个问题的,但刚刚看到你的更新说明你已经做到了。其次,我认为
ViewBag
只填充了一个动作,这与您在构造函数中给出的示例不同。在一个完全不同的注释中,我刚刚读到
StructureMap已被屏蔽。
ViewBag很容易从构造函数访问。我还没有听说过StructureMap,我得看看是否能找到链接。好的,我在访问ViewBag的构造函数上得到了更正。至于日落,它位于框架的主要位置(…)[非常好的解决方案。与控制器分离非常聪明。现在还不能授予奖金,但它是你的。@ScottBaker很乐意提供帮助。@ScottBaker在Asp.Net Core中期待的一件很酷的事情是视图允许强类型依赖项注入。ie
@InjectiaApplicationConfiguration部分AppConfig
参考
public class MvcRegistry : Registry
{
    public MvcRegistry()
    {
        For<BundleCollection>().Use(BundleTable.Bundles);
        For<RouteCollection>().Use(RouteTable.Routes);
        For<IPrincipal>().Use(() => HttpContext.Current.User);
        For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
        For<ICurrentUser>().Use<CurrentUser>();
        For<HttpSessionStateBase>()
            .Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
        For<HttpContextBase>()
            .Use(() => new HttpContextWrapper(HttpContext.Current));
        For<HttpServerUtilityBase>()
            .Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server));
        For<IApplicationConfigurationSection>()
            .Use(GetConfig());

        Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());
    }

    private IApplicationConfigurationSection GetConfig()
    {
        var config = ConfigurationManager.GetSection("application") as ApplicationConfigurationSection;
        return config; // this always returns a valid instance
    }
}
`Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());`