views:

164

answers:

4

I'm registering components with the following code:

StandardKernel kernel = new StandardKernel();

string currentDirectory = Path.GetDirectoryName(GetType().Assembly.Location)
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    if (!Path.GetDirectoryName(assembly.Location).Equals(currentDirectory)) 
        continue;

    foreach (var type in assembly.GetTypes())
    {
        if (!type.IsComponent()) 
    continue;

        foreach (var @interface in type.GetInterfaces())
    kernel.Bind(@interface).To(type).InSingletonScope();
    }
}

Then I have a class which implements two interfaces:

class StandardConsole : IStartable, IConsumer<ConsoleCommand>

If I Resolve IStartable I get one instance, if I Resolve IConsumer I get another. How do I get the same instance for both interfaces?

Please don't reply if you haven't used autofac or ninject

I've tried with both ninject and autofac :(

A: 

This is me taking a wild stab in the dark as I don't know Autofac.

If you add:

build.RegisterType<StandardConsole>.As(StandardConsole).SingleInstance()

then shouldn't it resolve IStartable to StandardConsole then StandardConsole to the singleton instance of StandardConsole? Ditto with IConsumer.

EDIT: From logging at your blog, couldn't you change the following:

assemblies.Each(assembly => assembly.FindComponents((i, c) => builder.RegisterType(c).As(i).SingleInstance()));

to

assemblies.Each(assembly => assembly.FindComponents((i, c) => {
    builder.RegisterType(c).As(i).SingleInstance();
    builder.RegisterType(c).As(c).SingleInstance();
}));
Wysawyg
See my comment for dave thieben
jgauffin
A: 

I'm not familiar with Autofac, but you ought to be able to Register for one type a lambda expression that returns the Resolve of the other type.

something like:

builder.Register<IStartable>().As<StandardConsole>().Singleton();
builder.Register<IConsumer<ConsoleCommand>>().As( x => builder.Resolve<IStartable>() );
dave thieben
No can do. I scan all assemblies in the application directory after classes with a ComponentAttribute and register them with all interfaces that they implement. That makes it quite hard to do what you suggest. http://blog.gauffin.org/2010/07/simplified-autofac-registrations/
jgauffin
+2  A: 
builder.RegisterType<StandardConsole>()
   .As<IStartable>()
   .As<IConsumer<ConsoleCommand>>()
   .SingleInstance();

Very widely used feature of Autofac- any problems then there is a bug somewhere :)

Hth Nick

Edit By the looks of it, you're after the overload of As() that takes an IEnumerable<Type>() - check out all of the As() overloads using IntelliSense, something there should fit your scenario. As another commenter noted, you need to update the question with all of the info.

Nicholas Blumhardt
No, I do not want to register using IEnumerable<Type>. It's a built in feature in autofac. Also, i can't use generic parameters since I'm using reflection to register all components.
jgauffin
I know the feature you mean (I wrote it ;)) - the one I'm suggesting is different. If you have a list of the interfaces you want to expose (i1, i2, i3..) you can just pass the whole list to a single As() call. You might also check out RegisterAssemblyTypes(myAsm).AsImplementedInterfaces(), which can be extended to do what your article is proposing http://code.google.com/p/autofac/wiki/Scanning - you're welcome to work through this via the Autofac discussion forum if you like.
Nicholas Blumhardt
Sorry =) Just got tired of answer from people that hadn't used autofac. I've updated my answer below with code from the Scanning article. Thanks!
jgauffin
+1  A: 

Updated with suggestion from Nicholas:

Here is how it's done in autofac

    private void BuildComponents(ContainerBuilder builder)
    {
        string currentDirectory = Path.GetDirectoryName(GetType().Assembly.Location);
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            if (!Path.GetDirectoryName(assembly.Location).Equals(currentDirectory))
                continue;

            builder.RegisterAssemblyTypes(assembly)
                .Where(t => t.IsComponent())
                .AsImplementedInterfaces()
                .SingleInstance();
        }
    }

    public static bool IsComponent(this Type value)
    {
        return value.GetType().GetCustomAttributes(typeof (ComponentAttribute), true).Length > 0;
    }
jgauffin