Asked  7 Months ago    Answers:  5   Viewed   56 times

I find that my constructors are starting to look like this:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

with ever increasing parameter list. Since "Container" is my dependency injection container, why can't I just do this:

public MyClass(Container con)

for every class? What are the downsides? If I do this, it feels like I'm using a glorified static. Please share your thoughts on IoC and Dependency Injection madness.

 Answers

30

You are right that if you use the container as a Service Locator, it's more or less a glorified static factory. For lots of reasons I consider this an anti-pattern (also see this excerpt from my book).

One of the wonderful benefits of Constructor Injection is that it makes violations of the Single Responsibility Principle glaringly obvious.

When that happens, it's time to refactor to Facade Services. In short, create a new, more coarse-grained interface that hides the interaction between some or all of the fine-grained dependencies you currently require.

Tuesday, June 1, 2021
 
Sabya
answered 7 Months ago
86

Read about pdo prepared statements

Here is an example

$stmt = $dbh->prepare("SELECT * FROM tables WHERE names = :name");
$stmt->execute(array(':name' => $name));
Friday, May 28, 2021
 
Pegues
answered 7 Months ago
57

I have been using Ninject, and found that it's a pleasure to work with. Everything is set up in code, the syntax is fairly straightforward and it has a good documentation (and plenty of answers on SO).

So basically it goes like this:

Create the view model, and take the IStorage interface as constructor parameter:

class UserControlViewModel
{
    public UserControlViewModel(IStorage storage)
    {

    }
}

Create a ViewModelLocator with a get property for the view model, which loads the view model from Ninject:

class ViewModelLocator
{
    public UserControlViewModel UserControlViewModel
    {
        get { return IocKernel.Get<UserControlViewModel>();} // Loading UserControlViewModel will automatically load the binding for IStorage
    }
}

Make the ViewModelLocator an application wide resource in App.xaml:

<Application ...>
    <Application.Resources>
        <local:ViewModelLocator x:Key="ViewModelLocator"/>
    </Application.Resources>
</Application>

Bind the DataContext of the UserControl to the corresponding property in the ViewModelLocator.

<UserControl ...
             DataContext="{Binding UserControlViewModel, Source={StaticResource ViewModelLocator}}">
    <Grid>
    </Grid>
</UserControl>

Create a class inheriting NinjectModule, which will set up the necessary bindings (IStorage and the viewmodel):

class IocConfiguration : NinjectModule
{
    public override void Load()
    {
        Bind<IStorage>().To<Storage>().InSingletonScope(); // Reuse same storage every time

        Bind<UserControlViewModel>().ToSelf().InTransientScope(); // Create new instance every time
    }
}

Initialize the IoC kernel on application startup with the necessary Ninject modules (the one above for now):

public partial class App : Application
{       
    protected override void OnStartup(StartupEventArgs e)
    {
        IocKernel.Initialize(new IocConfiguration());

        base.OnStartup(e);
    }
}

I have used a static IocKernel class to hold the application wide instance of the IoC kernel, so I can easily access it when needed:

public static class IocKernel
{
    private static StandardKernel _kernel;

    public static T Get<T>()
    {
        return _kernel.Get<T>();
    }

    public static void Initialize(params INinjectModule[] modules)
    {
        if (_kernel == null)
        {
            _kernel = new StandardKernel(modules);
        }
    }
}

This solution does make use of a static ServiceLocator (the IocKernel), which is generally regarded as an anti-pattern, because it hides the class' dependencies. However it is very difficult to avoid some sort of manual service lookup for UI classes, since they must have a parameterless constructor, and you cannot control the instantiation anyway, so you cannot inject the VM. At least this way allows you to test the VM in isolation, which is where all the business logic is.

If anyone has a better way, please do share.

EDIT: Lucky Likey provided an answer to get rid of the static service locator, by letting Ninject instantiate UI classes. The details of the answer can be seen here

Tuesday, June 1, 2021
 
laurent
answered 7 Months ago
79

This is an interesting problem. How can you dependency inject re-usable assemblies that do not have an entry point. I would really like to see other people's answer.

Dependency injection is the responsibility of the entry-point assembly. Yet, if you have a lot of classes and assemblies each needing DI, then it is possible that they are left-off for some classes/assemblies and the task becomes onerous.

Solution One

Using convention over configuration. You stick to a rule of class Foo implementing IFoo, etc. A lot of DI frameworks have the means to set it up using convention.

Solution two

Above solution does not solve all problems since sometimes you need to parameterise the setup of the injection. Here is how I have solved the problem (especially for those assemblies loaded by MEF and this is for AutoFac):

Created an interface IIocInstaller where container (or builder is passed)

public interface IIocInstaller
{
    void Setup(ContainerBuilder builder);
}

Created an assembly attribute that flags assemblies needing DI:

[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}

In each assembly, I create a class that sets up DI:

[assembly: ExportAssembly]
namespace This.That
{

    [Export(typeof(IIocInstaller))]
    public class IocInstaller : IIocInstaller
    {
        public void Setup(ContainerBuilder builder)
        {
            ....
        }
    }
}

Then in the entry point, I have a common code which looks through all loaded assemblies (including MEFed ones) that have the assembly attribute and then look for the type implementing the IIocInstaller and then call Setup on them.

Sunday, August 1, 2021
 
BaajiRao
answered 4 Months ago
11

Give TinyIoC a try - http://www.grumpydev.com/2010/03/02/announcing-tinyioc-an-easy-to-use-hassle-free-inversion-of-control-container/

Cheers,

ChrisNTR

Thursday, August 12, 2021
 
Pratap Vhatkar
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share