Вернуть одинаковый экземпляр для нескольких интерфейсов
Я регистрирую компоненты со следующим кодом:
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>
, я получаю другой.
Как мне получить тот же экземпляр для обоих интерфейсов?
Ответы
Ответ 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>() );