0

I've created this code:

public class AddonsModule : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        this.Bind(b => b.FromAssembliesMatching("*")
            .SelectAllClasses()
            .InheritedFrom(typeof(UIExtensibility.AbstractAddon))
            .BindWith(new AddonBindingGenerator())
        );
    }

    private class AddonBindingGenerator : IBindingGenerator
    {

        public System.Collections.Generic.IEnumerable<Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(System.Type type, Ninject.Syntax.IBindingRoot bindingRoot)
        {
            if (type.IsInterface || type.IsAbstract)
                yield break;

            yield return bindingRoot.Bind(type).ToProvider(typeof(UIExtensibility.AbstractAddon));
        }
    }

    private class AddonProvider : IProvider<UIExtensibility.AbstractAddon>
    {

        public object Create(IContext context)
        {
            return null;
        }

        public Type Type
        {
            get { throw new NotImplementedException(); }
        }
    }
}

AddonProvider seems be avoided. This is never performed.

When I perform: kernel.GetAll<UIExtensibility.AbstractAddon>(), AddonProvider.Create method is never performed.

Could you tell me what's wrong? I'll appreciate a lot your help.

Thanks for all.

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • please clean up your code so it's better readable on this site. Format it so there is no sideways scrolling necessary and *remove any code which is commented out*. – BatteryBackupUnit Aug 07 '15 at 05:09

3 Answers3

1

AddOnProvider is inheriting from IProvider<T> instead of UIExtensibility.AbstractAddon.

also, you may have issues binding to private inner classes. make AddOnProvider a public top level class.

Dave Thieben
  • 5,388
  • 2
  • 28
  • 38
1

You're binding a specific type which inherits from typeof(UIExtensibility.AbstractAddon) to a provider. For example, there could be a class Foo : UIExtensibility.AbstractAddon. Now your convention binding translates to this:

Bind<Foo>().ToProvider<AddonProvider>();

Now, kernel.GetAll<UIExtensibility.AbstractAddon>() however is looking for bindings made like:

Bind<UIExtensibility.AbstractAddon>().To...

Fix It

So what you need to do is change the line

bindingRoot.Bind(type).ToProvider(new AddonProvider());

to:

bindingRoot.Bind(typeof(UIExtensibility.AbstractAddon)).ToProvider<AddonProvider>();

Furthermore

  • you're line object f = bindingRoot.Bind(type).ToProvider(new AddonProvider()); is never returning the binding (object f).
  • does UIExtensibility.AbstractAddon implement IProvider?
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
0

Thanks for your answer and comments.

I believe the trouble is on I'm not quite figuring out how this "generic" binding process works.

I'm going to try writing my brain steps process out:

  1. I need to bind every AbstractAddon implementation inside addons assemblies folder. So, I think this code is right, but I'm not sure at all.

    this.Bind(b => b.FromAssembliesMatching("*")
        .SelectAllClasses()
        .InheritedFrom(typeof(UIExtensibility.AbstractAddon))
        .BindWith(new AddonBindingGenerator())
    );
    
  2. My AbstractAddon is like:

    public abstract class AbstractAddon : IAddon
    {
    
        private object configuration;
    
        public AbstractAddon(object configuration)
        {
            this.configuration = configuration;
        }
    
        // IAddon interface
    
        public abstract string PluginId { get; }
    
        public abstract string PluginVersion { get; }
    
        public abstract string getCaption(string key);
    
        public abstract Type getConfigurationPanelType();
    
        public abstract System.Windows.Forms.UserControl createConfigurationPanel();
    
    }
    
  3. I guess I need to:

    foreach implementation of `AbstractAddon` found out,
        I need to "inject" a configuration object ->
            So, I guess I need to set a provider and provide this configuration object.
    

This would be my main way of thinking in order to solve this problem.

I've changed a bit my first approach. Instead of using a IBindingGenerator class, I've used the next:

    public class AddonsModule : Ninject.Modules.NinjectModule
    {
        public override void Load()
        {
            this.Bind(b => b.FromAssembliesMatching("*")
                .SelectAllClasses()
                .InheritedFrom(typeof(UIExtensibility.AbstractAddon))
                .BindAllBaseClasses()
                .Configure(c => c.InSingletonScope())
            );

            this.Bind<object>().ToProvider<ConfigurationProvider>()
                .WhenTargetHas<UIExtensibility.ConfigurationAttribute>();
        }

So, My ConfigurationProvider is:

private class ConfigurationProvider : IProvider<object>
{

    public object Create(IContext context)
    {
        return "configuration settings";
    }
}

And now, my AbstractAddon constructor contains the parameter annotated with ConfigurationAttribute as:

public AbstractAddon([Configuration]object configuration)
{
    this.configuration = configuration;
}

The problem now, NInject seems to ignore the configuration object provider. NInject generates a dump object, however, not perform ConfigurationProvider.Create method...

What I'm doing wrong, now? Is this approach really better than the last one? Thanks for all.

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • Instead of just showing the steps you're taking you should try to concisely explain the goal you need to achieve. Not how some design but the ultimate goal (ask yourself "why" five times ;-) ). With you'r current approach you're creating multiple bindings for `object` with the same condition: 'this.Bind().ToProvider() .WhenTargetHas();'. Not gonna work. Also, why would you even need a provider if the configuration object is kind of "static" - the same for every addon? Why is it an object? – BatteryBackupUnit Aug 07 '15 at 08:28
  • 1
    I don't understand what you mean with: _you're creating multiple bindings for object with the same condition: 'this.Bind().ToProvider() .WhenTargetHas();'_ I think I'm set a bind for `object` or 'string' or whichever class to a provider. I don't understand why this simple rule doesn't work... configuration object is not static, it depends of a concrete context (I gonna send every configuration object on GetAll(as a parameter array), and provider will receive them and choice between them. – Jordi Aug 07 '15 at 08:34
  • oh sorry, my bad. i was wrong. I thought it was part of the binding generator but i now see that it's not. – BatteryBackupUnit Aug 07 '15 at 08:48
  • It's really strange, no? I only set a provider for a `object` when this is annotated with `ConfigurationAttribute`... It might only work, no? – Jordi Aug 07 '15 at 11:35
  • Are you creating an instance of `AbstractAddon` or of a derived class? If it's a derived class then it's missing the `ConfigurationAttribute` (which is not inherited!). Also, if there's a constructor with more parameters ninject by default will choose the other constructor. If you need more info you'll need to upload complete sample code (p.Ex. github repository). – BatteryBackupUnit Aug 07 '15 at 12:07
  • Ok. I'm trying to create a `AbstractAddon` derived class. Mmm, I'm not able to add `ConfigurationAttribute` in `AbstractAddon` derive due to they are created out of my scope. Remind I'm looking for a third party assemblies... Mmm, Any ideas? Perhaps using [Inheritance property](https://msdn.microsoft.com/en-us/library/system.attributeusageattribute.inherited(v=vs.110).aspx) to True in `ConfigurationAttribute` – Jordi Aug 08 '15 at 17:22