每个区域的Autofac依赖项

时间:2012-12-28 20:33:36

标签: asp.net-mvc autofac asp.net-mvc-areas

我正在使用Autoface创建一个新的MVC4站点,该站点具有公共消费者站点以及用于管理面向消费者的站点的管理区域。管理站点将位于不同的区域,使用与面向消费者的站点相同的服务,但不具备某些自定义品牌功能。

我遵循了其他地方给出的有关ViewDataFactory的建议,该ViewDataFactory为视图提供了一组共享数据。我的目标是根据您所在的区域提供不同的ViewDataFactory。

例如,这是实现IViewDataFactory

的服务
builder.RegisterType<SelfServiceViewDataFactory>().As<IViewDataFactory>();

这给了我一个注入我所有控制器的ViewFactory。然而,我试图实现的是这样的(不是功能代码):

builder.RegisterType<ViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase1);    
builder.RegisterType<DifferentViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase2);    

控制器类型或MVC区域将决定解析哪个服务。

修改

澄清我的帖子有两个问题:

  1. Autofac有没有办法说“只针对X类,Y型服务将由实例Z提供”?
  2. 有没有办法根据正在使用的组件区域来更改Autofac行为?
  3. 从我读过的所有内容来看,#1的答案似乎都是“不”,除非您有一个参数用于检查要提供的组件。我知道Ninject可以提供基于命名空间的依赖,因此其他框架似乎可以处理这种情况。似乎解决方案是提供参数或定义两个不同的服务。

    我还没有真正看过很多关于Autofac和MVC领域的讨论,所以我猜测#2在没有自定义解决方案的情况下也是不可能的。谢谢!

1 个答案:

答案 0 :(得分:2)

使用命名服务可能是您的最佳选择。所以你会做类似的事情:

builder
    .RegisterType<ViewDataFactory>()
    .Named<IViewDataFactory>("Area1");    

builder
    .RegisterType<DifferentViewDataFactory>()
    .As<IViewDataFactory>("Area2");

然后,如果你想避免必须手动注册你的控制器。您可以使用我刚拼凑在一起并且未经过测试的代码:

将此属性放在全球可访问的位置:

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public class ServiceNamedAttribute : Attribute
{
    private readonly string _key;

    public ServiceNamedAttribute(string key)
    {
        _key = key;
    }

    public string Key { get { return _key; } }
}

将此模块添加到Autofac配置中:

public class ServiceNamedModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry registry, IComponentRegistration registration)
    {
        registration.Preparing +=
            (sender, args) =>
            {
                if (!(args.Component.Activator is ReflectionActivator))
                    return;

                var namedParameter = new ResolvedParameter(
                    (p, c) => GetCustomAttribute<ServiceNamedAttribute>(p) != null,
                    (p, c) => c.ResolveNamed(GetCustomAttribute<ServiceNamedAttribute>(p).Name, p.ParameterType));

                args.Parameters = args.Parameters.Union(new[] { namedParameter });
            };
    }

    private static T GetCustomAttribute<T>(ParameterInfo parameter) where T : Attribute
    {
        return parameter.GetCustomAttributes(typeof(T), false).Cast<T>().SingleOrDefault();
    }
}

然后你仍然可以通过修饰构造函数来自动注册你的控制器:

public class Controller1
{
    public Controller1(ServiceNamed["Area1"] IViewDataFactory factory)
    { ... }
}