Hungry Beast
Hungry Beast

Reputation: 3725

Ninject Factory Pattern and Bindings

I am trying to implement the Ninject.Extensions.Factory pattern and my program is telling me my bindings aren't right, but I can't figure out why. I keep getting an "Error activating IHashable. No matching bindings are available, and the type is not self-bindable" exception thrown. The relevant areas of my code are below:

public interface IHashable
{
    FileInfo File { get; }

    string ComputeHash();
}

public interface IHashableFactory
{
    IHashable GetNew(FileInfo file);
}

public class MD5ChecksumProvider : IHashable
{
    private FileInfo _file;

    public FileInfo File
    {
        get { return _file; }
    }

    public MD5ChecksumProvider(FileInfo file)
    {
        if (file == null)
            throw new ArgumentNullException("file");

        _file = file;
    }

    public string ComputeHash()
    {
        // implementation
    }
}

public class AppFileProvider : IAppFileProvider
{
    private IHashableFactory _hashFactory;

    public IHashableFactory HashProvider
    {
        get { return _hashFactory; }
    }

    public AppFileProvider(IHashableFactory hashProviderFactory)
    {
        _hashFactory = hashProviderFactory;
    }

    public string GetChecksum(FileInfo fileInfo)
    {
        var hasher = _hashFactory.GetNew(fileInfo);
        return hasher.ComputeHash();
    }
}

public class BindingProviders : NinjectModule
{
    public override void Load()
    {
        Bind<IHashable>()
            .To<MD5ChecksumProvider>();
    }
}

public class BindingFactories : NinjectModule
{
    public override void Load()
    {
        Bind<IHashableFactory>()
            .ToFactory();
    }
}

// my DI container
public sealed class Container : IDisposable
{
    private bool _isDisposed;
    private IKernel _kernel;
    private BindingFactories _bindingFactories;
    private BindingObjects _bindingObjects;
    private BindingProviders _bindingProviders;

    public Container()
    {
        _isDisposed = false;

        _bindingFactories = new BindingFactories();
        _bindingObjects = new BindingObjects();
        _bindingProviders = new BindingProviders();

        _kernel = new StandardKernel(_bindingObjects, _bindingProviders, _bindingFactories);
    }

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

    public void Dispose()
    {
        // nothing worth seeing
    }

    private void Dispose(bool disposing)
    {
        // nothing worth seeing
    }
}

// the program (composition root)
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        using (var container = new Container())
        {
            var fileProvider = container.Get<IAppFileProvider>();

            foreach (var file in files)
            {
                string hash = fileProvider.GetChecksum(storePath, file); // this line throws "Error activating IHashable. No matching bindings are available, and the type is not self-bindable.""
            }
        }
    }
}

I feel like my bindings are setup correctly but I must be missing something obvious. Any ideas why I'm getting the exception from the above code?

Upvotes: 3

Views: 1132

Answers (1)

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13233

This is caused by a feature of Ninject.Extensions.Factory. It treats methods which start with Get differently from those which don't. If you rename IHashableFactory.GetNew to Create or Make everything works fine.

The "Get" feature is described here:

The default instace provider of the extension has the convention that it tries to return an instance using a named binding whenever a method starts with “Get”. E.g. IFoo GetMySpecialFoo() is equal to

resolutionRoot.Get<IFoo>("MySpecialFoo");


Since i think this is not obvious to the user and the exception isn't helpful at all in this regard, i have filed an issue report here

Upvotes: 3

Related Questions