简体   繁体   中英

Web Api and Dependency Injection

I have a few questions regarding some best practices when it comes to Dependency Injection and Web Api. I am using Autofac, but I think this would be the same regardless of the IoC. This is a very generic example, but I can't logically think of the best way to make the entire app loosely coupled. In my code, AppControls is always dependent on the Control class. Below are my code snippets:

AutofacConfig :

public static void Register(HttpConfiguration config)
{

    // Create builder
    var builder = new ContainerBuilder();

    // Register your Web API controllers.
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register types
    builder.RegisterType<AppContents>().As<IAppContents>();
    builder.RegisterType<AppControls>().As<IAppControls>();
    builder.RegisterType<Control>().As<IControl>();

    // Set the dependency resolver to be Autofac.
    var container = builder.Build();
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

}

AppController :

public class AppController : ApiController
{

    private readonly IAppContents _appContents = null;

    public AppController(IAppContents appContents)
    {
        if (appContents == null)
            throw new ArgumentNullException("appContents");
        _appContents = appContents;
    }

    public IAppContents Get()
    {
        return _appContents;
    }
}

AppContents/IAppContents

public class AppContents : IAppContents
{

    public AppContents(IAppControls appControls)
    {
        if (appControls == null)
            throw new ArgumentNullException("appControls");
        AppControls = appControls;
    }

    public IAppControls AppControls { get; set; }
}

public interface IAppContents
{
    IAppControls AppControls { get; set; }
}

AppControls/IAppControls

public class AppControls : IAppControls
{

    public AppControls()
    {

        //////////////////////////////////
        // Tightly coupled
        /////////////////////////////////

        // Controls1
        var controls1 = new List<IControl>();
        controls1.Add(new Control("Control1", "1", null));
        controls1.Add(new Control("Control2", "2", null));
        controls1.Add(new Control("Control3", "3", null));
        Controls1 = controls1;

        // Controls2
        var controls2 = new List<IControl>();
        controls2.Add(new Control("Control1", "1", null));
        controls2.Add(new Control("Control2", "2", null));
        controls2.Add(new Control("Control3", "3", null));
        Controls2 = controls2;

        // Controls3
        var controls3 = new List<IControl>();
        controls3.Add(new Control("Control1", "1", null));
        controls3.Add(new Control("Control2", "2", null));
        controls3.Add(new Control("Control3", "3", null));
        Controls3 = controls3;

    }

    public IEnumerable<IControl> Controls1 { get; set; }
    public IEnumerable<IControl> Controls2 { get; set; }
    public IEnumerable<IControl> Controls3 { get; set; }
}

public interface IAppControls
{
    IEnumerable<IControl> Controls1 { get; set; }
    IEnumerable<IControl> Controls2 { get; set; }
    IEnumerable<IControl> Controls3 { get; set; }
}

Control/IControl

public class Control : IControl
{

    public Control(string text, string value, string group)
    {
        Text = text;
        Value = value;
        Group = group;
    }

    public string Text { get; set; }
    public string Value { get; set; }
    public string Group { get; set; }
}

public interface IControl
{
    string Group { get; set; }
    string Text { get; set; }
    string Value { get; set; }
}

Regardless of the way I can think about it, I will always have to call 'new Control(..)'. Any advice will be greatly appreciated.

Dependency Injection makes it simple to manage dependencies between objects. It's therefore easier to break coherent functionality off into separate contracts (interfaces), and thus solve the problem of swapping out object dependencies during runtime or compile time. It doesn't mean you'll never have to instantiate something yourself again.

In your case, the controller doesn't need to bother knowing how to instantiate IAppContents, which in turn don't need to know that about IAppControls (lack of "new AppContents").

However, IControl looks like some form of static data, without behaviour, so it looks more like a newable than an injectable . A common scenario would've been for the IAppControls to have a handler injected through which you'd be able to read that data from somewhere.

That being said, you don't need loose coupling to implement dependency injection. You can inject a specific Control instance without making an abstracted version of your model - unless you plan on swapping it out with similar but varying Control models (for example, during unit testing).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM