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

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

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

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

32
задан CodeCaster 30 January 2017 в 15:22
поделиться

4 ответа

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

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

Hth Nick

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

71
ответ дан 27 November 2019 в 20:16
поделиться

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

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

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

, тогда не следует ли разрешать IStartable в StandardConsole, а затем StandardConsole в одноэлементный экземпляр 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();
}));
0
ответ дан 27 November 2019 в 20:16
поделиться

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

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

builder.Register<IStartable>().As<StandardConsole>().Singleton();
builder.Register<IConsumer<ConsoleCommand>>().As( x => builder.Resolve<IStartable>() );
0
ответ дан 27 November 2019 в 20:16
поделиться

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

Вот как это сделано в 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
ответ дан 27 November 2019 в 20:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: