2010-07-07 61 views
25

我注册的组件用下面的代码:返回同一个实例多个接口

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

这个问题应该分成两个,一个用于Ninject,另一个用于autofac。 – 2012-02-22 00:20:30

+0

@JeffWalkerCodeRanger:你给了-1? :) – jgauffin 2012-02-22 05:40:00

+1

在Ninject方面有3或4次的决斗,请参阅http://stackoverflow.com/questions/3147996/binding-singleton-to-multiple-services-in-ninject在此基础上删除ninject标签。建议删除ninject方面的问题,因为这使得无法回答的问题 – 2012-09-12 08:55:01

回答

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

非常广泛的应用功能的任何问题,再有就是某处的一个错误:)

H个 尼克

编辑由看起来,你是在As()的重载之后,需要IEnumerable <类型>() - 使用IntelliSense检查所有的As()重载,其中应符合您的方案。正如另一位评论者指出的那样,您需要用所有信息更新问题。

+0

不,我不想使用IEnumerable 进行注册。这是autofac中的一项内置功能。此外,我不能使用泛型参数,因为我使用反射来注册所有组件。 – jgauffin 2010-07-08 15:59:57

+2

我知道你的意思(我写它)的特征 - 我建议的特征是不同的。如果你有一个你想要公开的接口列表(i1,i2,i3 ..),你可以将整个列表传递给一个As()调用。您还可以查看RegisterAssemblyTypes(myAsm).AsImplementedInterfaces(),可以扩展它来完成您的文章提出的http://code.google.com/p/autofac/wiki/Scanning - 欢迎您完成如果你喜欢,可以通过Autofac论坛。 – 2010-07-08 23:15:28

+0

对不起=)刚刚厌倦了没有使用autofac的人的回答。我使用扫描文章中的代码更新了我的答案。谢谢! – jgauffin 2010-07-09 08:54:07

0

这是我在黑暗中狂野刺伤,因为我不知道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

查看我对dave thieben的评论 – jgauffin 2010-07-07 18:45:55

0

我不熟悉Autofac,但你应该能够为一个类型注册一个返回另一个类型的Resolve的lambda表达式。

类似:Autofac-的

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

不能做。我使用ComponentAttribute在类之后扫描应用程序目录中的所有程序集,并将它们注册到它们实现的所有接口。这使得很难做到你的建议。 http://blog.gauffin.org/2010/07/simplified-autofac-registrations/ – jgauffin 2010-07-07 18:45:05

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

做我知道这是一个古老的线程,但这里是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>()); 
+0

使用ActivationContext时这不起作用。 – 2012-02-22 00:19:19

+0

@Jeff:见http://www.planetgeek.ch/2011/12/30/new-features-and-changes-of-ninject-3-0/ – 2012-09-12 08:31:42