Вернуть один и тот же экземпляр для нескольких интерфейсов - PullRequest
29 голосов
/ 07 июля 2010

Я регистрирую компоненты со следующим кодом:

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

Тогда у меня есть класс, который реализует два интерфейса:

class StandardConsole : IStartable, IConsumer<ConsoleCommand>

Если я разрешу IStartable, я получу один экземпляр, если я разрешу IConsumer<ConsoleCommand>, я получу другой.

Как получить один и тот же экземпляр для обоих интерфейсов?

Ответы [ 5 ]

64 голосов
/ 08 июля 2010
builder.RegisterType<StandardConsole>()
   .As<IStartable>()
   .As<IConsumer<ConsoleCommand>>()
   .SingleInstance();

Очень широко используемая особенность Autofac - любые проблемы, тогда где-то есть ошибка:)

Hth Ник

Редактировать Судя по всему, вы после перегрузки As (), которая принимает IEnumerable () - проверьте все перегрузки As () с помощью IntelliSense, что-то там должен соответствовать вашему сценарию. Как заметил другой комментатор, вам нужно обновить вопрос со всей информацией.

2 голосов
/ 14 июля 2011

Я знаю, что это старая ветка, но вот решение для 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>());
2 голосов
/ 08 июля 2010

Обновлено с предложением Николая:

Вот как это делается в 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;
    }
0 голосов
/ 07 июля 2010

Я не знаком с Autofac, но вы должны иметь возможность зарегистрировать для одного типа лямбда-выражение, которое возвращает Resolve другого типа.

что-то вроде:

builder.Register<IStartable>().As<StandardConsole>().Singleton();
builder.Register<IConsumer<ConsoleCommand>>().As( x => builder.Resolve<IStartable>() );
0 голосов
/ 07 июля 2010

Это я делаю дикий удар в темноте, поскольку я не знаю Autofac.

Если вы добавите:

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

, то не должно ли это разрешить IStartable в StandardConsoleStandardConsole для единственного экземпляра StandardConsole?То же самое с IConsumer.

РЕДАКТИРОВАТЬ: от входа в свой блог, вы не могли бы изменить следующее:

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

на

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