开发者

Return same instance for multiple interfaces

开发者 https://www.devze.com 2023-01-05 21:10 出处:网络
I\'m re开发者_如何学运维gistering components with the following code: StandardKernel kernel = new StandardKernel();

I'm re开发者_如何学运维gistering 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<ConsoleCommand> I get another.

How do I get the same instance for both interfaces?


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.


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;
    }


I know this is an old thread, but here is the solution for Ninject.

kernel.Bind<StandardConsole>().ToSelf().InSingletonScope();
kernel.Bind<IStartable>().ToMethod(ctx => ctx.Kernel.Get<StandardConsole>());
kernel.Bind<IConsumer<ConsoleCommand>>().ToMethod(ctx => ctx.Kernel.Get<StandardConsole>());


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>() );


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();
}));
0

精彩评论

暂无评论...
验证码 换一张
取 消