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

点点圈 提交于 2020-01-25 08:28:25

问题


I am struggling with wiring dependencies through autofac in my WebApi 2 project. I have a following interface and class that i'd like to inject in my GET and POST controller actions,

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;
    }
}

I 'd like IRepository to be injected in controller like this,

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();
            }
    }

IContext object to be injected in MyRepository has to be fetched from a factory, something like this

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;
            }
    }
}

I am not sure how to wire all the classes and convert logic in factory classes by injecting relationships through Autofac so that context id passed in url is passed to ContextConfigurationFactory.Get and instantiate ConcreteContext object when not found in hash and eventually Autofac injecting right context object in MyRepository before passing it on to Get action in the controller.


回答1:


Let's simplify this a bit. What you're trying to do is:

  • Get the context ID from a route parameter.
  • Use that route parameter in the factory to create a context.

The rest seems pretty much peripheral - the repository, the controller, all that. The crux of the question is that you need to get a route parameter into your factory.

Given that, let's put together some simplified code:

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; }
}

That's basically what you have:

  • An IContext interface that things need.
  • A ContextFactory that is basically responsible for building these things.
  • A Context concrete implementation of IContext that is built by the factory.

I would probably do something like this:

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();

Now when you resolve IContext it will use your factory, get the current context ID from route data, and pass it through the factory.

I will leave the following for you to look into:

  • What happens if the route parameter isn't there? (Autofac won't let you return null.)
  • What happens if the route parameter has invalid data?
  • The route parameter is pretty hackable, is this a security risk?

...and so on.



来源:https://stackoverflow.com/questions/49241204/how-do-i-resolve-a-webapi-dependency-in-autofac-that-requires-a-parameter-from-t

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!