2010-07-07 67 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