1

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

我遵循了其他地方给出的建议,即拥有一个 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 行为?

从我一直在阅读的所有内容来看,#1 的答案似乎是“否”,除非您有一个参数可用于检查要提供的组件。我知道 Ninject 可以提供基于命名空间的依赖项,因此其他框架似乎可以处理这种情况。似乎解决方案是提供一个参数或定义两个不同的服务。

我还没有真正看到太多关于 Autofac 和 MVC 领域的讨论,所以我猜如果没有自定义解决方案,#2 也是不可能的。谢谢!

4

1 回答 1

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)
    { ... }
}
于 2013-01-02T15:52:11.993 回答