Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am developing a MVC application using .net, I am using autofac as the IoC container.

I have service class which needs a parameter in the constructor. And the parameter is resolved at run time from the input URL.

public interface IService {
 ...
}

public Service : IService {

 public Service(string input) {
 }
 ...

}

public class MyController : ApiController { 
    private IService _service;

    public MyController (IService service)
    {
        _service = service;
    }
}

I am not sure what is the best way to pass that parameter when the Service class is created. What is the best practice of dealing this issue?

share|improve this question

2 Answers

up vote 2 down vote accepted

You have a couple of options, generally depending on how tightly coupled you want to be to HttpContext.

The first option is to register using a lambda:

builder.Register(c => new Service(HttpContext.Current.Request.RawUrl)).As<IService>();

The benefit to this is it's simple and easy to read. The drawback is that, as you refactor your Service class, possibly adding more constructor parameters, you'll also have to refactor your registrations. You're also tightly coupled to HttpContext so you'll have trouble using this registration in a unit test.

The second option is that you can register with a parameter. You'll want to also have the AutofacWebTypesModule registered.

// Automatically provides HttpRequestBase registration.
builder.RegisterModule<AutofacWebTypesModule>();
// Register the component using a parameter.
builder.RegisterType<Service>()
       .As<IService>()
       .WithParameter(
         // The first lambda determines which constructor parameter
         // will have the value provided.
         (p, c) => p.ParameterType == typeof(string),
         // The second lambda actually gets the value.
         (p, c) => {
           var request = c.Resolve<HttpRequestBase>();
           return request.RawUrl;
         });

The benefit to this is that it separates the actual construction of the object from the retrieval of the environment value. You can also use it in a unit test by adding test registrations for stub HttpRequestBase values. The drawback is it's a little longer and may feel more complex than required.

Either will work, it boils down to how you want to handle it.

share|improve this answer
cool, that helps – Stay Foolish Jun 10 at 23:16

Register that service using a delegate:

builder.Register<IService>(container =>
{ 
    return new Service(HttpContext.Current.Request.RawUrl);
});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.