Подтвердить что ты не робот

Вернуть одинаковый экземпляр для нескольких интерфейсов

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

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>, я получаю другой.

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

4b9b3361

Ответ 1

builder.RegisterType<StandardConsole>()
   .As<IStartable>()
   .As<IConsumer<ConsoleCommand>>()
   .SingleInstance();

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

Hth Ник

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

Ответ 2

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

Вот как это делается в 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;
    }

Ответ 3

Я знаю, что это старый поток, но вот решение для 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>());

Ответ 4

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

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

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

то не следует ли он разрешать IStartable для StandardConsole, а затем StandardConsole для экземпляра singleton 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();
}));

Ответ 5

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

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

builder.Register<IStartable>().As<StandardConsole>().Singleton();
builder.Register<IConsumer<ConsoleCommand>>().As( x => builder.Resolve<IStartable>() );