Search code examples
structuremapstructuremap3

No default instance or named instance 'Default' for requested plugin type


I'm trying to avoid referencing the concrete type library in my main project, but I'm getting this error:

No default instance or named instance 'Default' for requested plugin type StackExchangeChatInterfaces.IClient
1.) Container.GetInstance(StackExchangeChatInterfaces.IClient ,{username=; password=; defaultRoomUrl=; System.Action`2[System.Object,System.Object]=System.Action`2[System.Object,System.Object]})

I've setup my container to scan for assemblies, like so:

        var container = new Container(x =>
        {
            x.Scan(scan =>
            {
                scan.AssembliesFromApplicationBaseDirectory();
                scan.ExcludeNamespace("StructureMap");
                scan.WithDefaultConventions();
                scan.AddAllTypesOf<IMessageHandlers>();
            });
            //x.For<IClient>().Use<Client>(); //GetInstance will work if this line is not commented out.
        });

When I try to get an instance, I get the error, my code for getting an instance is here:

chatInterface = container
    .With("username").EqualTo(username)
    .With("password").EqualTo(password)
    .With("defaultRoomUrl").EqualTo(roomUrl)
    .With<Action<object, object>>(delegate(object sender, object messageWrapper)
        {
            string message = ((dynamic)messageWrapper).Message;
            Console.WriteLine("");
            Console.WriteLine(message);
            foreach (var item in messageHandlers)
            {
                item.MessageHandler.Invoke(message, chatInterface);
            }                        
        }).GetInstance<IClient>();

If I explicitly map the concrete class to the interface, everything works hunky dory, but that means I need to reference the project that Client is in, which I don't want to do.


Solution

  • This is really interesting. Looks like default conventions are not able to register types with such constructor (tried on both versions 2.6.3 and 3+). I was only registered when only parameterless constructor was specified. Looking at sources of both versions it is really suspicious as it should be registered. Deeper dive into the code would be needed...

    Anyway try using custom registration convention:

    public class ClientConvention : IRegistrationConvention
    {
        public void Process(Type type, Registry registry)
        {
            if (type.IsClass && !type.IsAbstract && !type.IsGenericType &&
                type.GetInterfaces().Contains(typeof(IClient)))
            {
                registry.For(typeof(IClient)).Use(type);
            }
        }
    }
    

    Configure it like this:

        var container = new Container(
                c => c.Scan(
                    s =>
                        {
                             s.ExcludeNamespace("StructureMap");
                             s.WithDefaultConventions();
                             s.Convention<ClientConvention>();
                             s.AddAllTypesOf<IMessageHandlers>();
                        }));
    

    and this should work just fine.