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

时间:2018-03-12 17:29:00

标签: autofac webapi2

我正在通过WebApi 2项目中的autofac来解决布线依赖问题。我有一个以下接口和类,我想在我的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注入关系来连接所有类并转换工厂类中的逻辑,以便在url中传递的上下文id传递给ContextConfigurationFactory.Get并在hash中找不到ConcreteContext对象并最终注入Autofac在将其传递给控制器​​中的Get动作之前,在MyRepository中使用正确的上下文对象。

1 个答案:

答案 0 :(得分:2)

让我们简化一下。你要做的是:

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

剩下的似乎是外围设备 - 存储库,控制器等等。问题的关键在于你需要在工厂中获得一个路线参数。

鉴于此,我们将一些简化的代码放在一起:

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
  • Context构建的IContext具体实现。

我可能会这样做:

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不会让你返回null。)
  • 如果路线参数包含无效数据会怎样?
  • 路由参数很难破解,这是一个安全隐患吗?

......等等。