简体   繁体   中英

Interface dependency hierarchy

I currently have a main class which might call another class which might call 2 or 3 others. The main class might create a Windows form as well.

So at the moment we might have:

public class MainClass
{
  ...
  AnotherClass = new AnotherClass();
  fmMain myForm = new fmMain();
}

public class AnotherClass
{
  ...
  DatabaseClass dbClass = new DatabaseClass();
  FileClass fClass = new FileClass();
}

As I see it, after refactoring and putting in constructor interface dependencies I can use an IOC container.

The problem is my entry point is the main class so all I can see to do is have all the dependencies in the main class constructor and then pass these down into the other classes and forms.

The issue is this could get very messy and the main class might have 10 dependencies most of which used in other classes. Is there an alternative?

Let the IoC container to do this.

Register AnotherClass as a dependency and then resolve it directly referring to container instance.

Dependencies should be defined locally to where they are required ie the dependencies should be defined on the constructors of the types, then use an IoC container to resolve all types. In this way the IoC takes care of "passing these down into the other classes and forms". When using an IoC container avoid using "new" whenever possible, and instead use the container to create instances. It will handle creation and injection of dependencies for you.

For example (using Ninject), the following demonstrates a Form which defines its own dependencies. The container will supply and inject all dependencies recursively when used to resolve an instance of the ProductForm .

Dependencies do not need to be injected into the entry-point class, but are specified as bindings in a module and then injected by the container when types such as Forms are resolved.

public class Program
{
    public Program()
    {
        IKernel kernel = new StandardKernel(new MainModule());

        Form form = kernel.Get<ProductForm>();

        form.Show();
    }
}

public class MainModule : NinjectModule
{
    public override void Load()
    {
        Bind<ProductForm>().ToSelf();
        Bind<IProductService>().To<ProductService>();
        Bind<IProductDb>().To<IProductDb>();
    }
}

internal class ProductForm : Form
{
    private readonly IProductService _productService;

    public ProductForm(IProductService productService)
    {
        _productService = productService;
    }
}

internal interface IProductService {}

internal class ProductService : IProductService
{
    private readonly IProductDb _productDb;

    public ProductService(IProductDb productDb)
    {
        _productDb = productDb;
    }
}

internal interface IProductDb {}

internal class ProductDb : IProductDb {}

It sounds like your Main class is your Composition Root . That's fine - it's not going to become messy if that's the only thing it does. This should be its single responsibility. In other words: your application entry point should be a Humble Object .

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