如何解决 Autofac 中需要路由参数的 WebAPI 依赖项?

How do I resolve a WebAPI dependency in Autofac that requires a parameter from the route?

我正在努力通过我的 WebApi 2 项目中的 autofac 连接依赖项。我有一个以下接口和 class 我想在我的 GET 和 POST 控制器操作中注入,

public interface IRepository
{
    IContext Context
        {
        get;
        }

    void SomeOperation();
}

public MyRepository : IRepository
{
    IContext _context;

    public MyRepository(IContext context)
    {
        _context = context;
    }

    public Context
    {
        get
        {
        return _context;
        }
    }

    public void SomeOperation
    {
    // Perform some operation using _context;
    }
}

我希望像这样将 IRepository 注入到控制器中,

public class MyController : ApiController
    {
        private readonly IRepository _repo;

        public ApplicationsController(IRepository repo)
            {
            _repo = repo;
            }

        // GET: api/v1/Contexts({contextId})
        public IHttpActionResult Get(string contextId)
            {
            _repo.SomeOperation();
            }
    }

要注入到 MyRepository 中的 IContext 对象必须从工厂中获取,像这样

public class ContextFactory
{
    Hashtable contextMap;

    IContext Get(string contextId)
    {
        if contextMap.Contains(contextId)
            return contextMap[contextId].Value;
        else
            {
                IContextConfiguration configuration = ContextConfigurationFactory.Get(contextId);

                IContext context = new ConcreteContext(configuration);
                contextMap.Add[contextId, context];

                return context;
            }
    }
}

我不确定如何通过 Autofac 注入关系来连接所有 classes 并转换工厂 classes 中的逻辑,以便将 url 中传递的上下文 ID 传递给ContextConfigurationFactory.Get 并在哈希中找不到时实例化 ConcreteContext 对象,最终 Autofac 在 MyRepository 中注入正确的上下文对象,然后再将其传递给控制器​​中的 Get 操作。

让我们稍微简化一下。您要做的是:

  • 从路由参数中获取上下文 ID。
  • 在工厂中使用该路由参数创建上下文。

其余的看起来几乎是外围的 - 存储库、控制器,所有这些。问题的症结在于你需要获取一个路由参数进入你的工厂。

鉴于此,让我们整理一些简化的代码:

public class ContextFactory
{
    public IContext Get(string contextId)
    {
        return new Context(contextId);
    }
}

public interface IContext
{
    string Id { get; }
}

public class Context : IContext
{
    public Context(string id)
    {
        this.Id = id;
    }

    public string Id { get; private set; }
}

这基本上就是你所拥有的:

  • 事物需要的 IContext 接口。
  • 一个ContextFactory,基本上负责构建这些东西。
  • 工厂构建的IContextContext具体实现。

我可能会这样做:

var builder = new ContainerBuilder();
builder.RegisterType<ContextFactory>();
builder.Register(ctx =>
{
    var routeData = HttpContext.Current.Request.RequestContext.RouteData;
    var id = routeData.Values["contextId"] as string;
    var factory = ctx.Resolve<ContextFactory>();
    return factory.Get(id);
}).As<IContext>()
.InstancePerLifetimeScope();

现在,当您解析 IContext 时,它将使用您的工厂,从路由数据中获取当前上下文 ID,并将其传递给工厂。

我将留下以下内容供您查看:

  • 如果路由参数不存在会怎样? (Autofac 不会让你 return 为空。)
  • 如果路由参数有无效数据会怎样?
  • 路由参数很容易破解,这是安全风险吗?

...等等。