IoC,Dll参考和汇编扫描

Jef*_*ght 10 c# structuremap inversion-of-control

虽然这个问题与StructureMap有关,但我的一般问题是:

在代码中使用IoC容器连接组件时(而不是通过xml进行配置),您通常需要对所有程序集进行显式项目/构建引用吗?

为什么单独的组件?因为:


"与其具体实现相关的独立程序集中的抽象类是实现这种分离的好方法." - 框架设计指南第91页


例:

假设我有PersonBase.dllBob.dll

Bob继承自抽象类PersonBase.它们都在Person命名空间中.但在不同的集会中.

我正在为PersonBase编程,而不是Bob.

回到我的主要代码中,我需要一个人.StructureMap可以扫描装配体.好的,我会问一下StructureMap!

现在,在我的主要代码中,我当然只是指PersonBase,而不是Bob.其实,我不希望我的代码知道任何关于鲍勃.没有项目参考,没有nuthin.这就是重点.

所以我想说:

//Reference: PersonBase.dll (only)
using Person;  
...

//this is as much as we'll ever be specific about Bob:
Scan( x=> { x.Assembly("Bob.dll"); }

//Ok, I should now have something that's a PersonBase (Bob). But no ?
ObjectFactory.GetAllInstances<PersonBase>().Count == 0
Run Code Online (Sandbox Code Playgroud)

没运气.我希望鲍勃做的工作是明确的:

//Reference: PersonBase.dll and Bob.dll
using Person; 
...
Scan( x => {x.Assembly("Bob.dll"); }

//If I'm explicit, it works. But Bob's just a PersonBase, what gives?
ObjectFactory.GetAllInstances<Bob>().Count == 1 //there he is!
Run Code Online (Sandbox Code Playgroud)

但是现在我必须在我的项目中引用Bob.dll,这正是我不想要的.

我可以使用Spring + Xml配置来避免这种情况.但后来我回到Spring + Xml配置......!

我是否遗漏了使用StructureMap的东西,或者作为一般原则,(流畅的)IoC配置是否需要明确引用所有程序集?

可能相关的问题: StructureMap和扫描组件

Jef*_*ght 15

我终于解决了这个问题.它看起来像这样:

IoC Uml http://img396.imageshack.us/img396/1343/iocuml.jpg

与组件

  • Core.exe
  • PersonBase.dll(由Core.exe 引用编译时)
  • Bob.dll(通过StructureMap Scan 加载运行时)
  • Betty.dll(通过StructureMap扫描加载运行时)

要使用StructureMap,我需要一个自定义的"ITypeScanner"来支持扫描程序集:

public class MyScanner : ITypeScanner {
  public void Process(Type type, PluginGraph graph) {

    if(type.BaseType == null) return;

    if(type.BaseType.Equals(typeof(PersonBase))) {
      graph.Configure(x => 
        x.ForRequestedType<PersonBase>()
        .TheDefault.Is.OfConcreteType(type));
    }
  }
} 
Run Code Online (Sandbox Code Playgroud)

所以我的主要代码如下:

ObjectFactory.Configure(x => x.Scan (
  scan =>
  {
    scan.AssembliesFromPath(Environment.CurrentDirectory 
    /*, filter=>filter.You.Could.Filter.Here*/);

    //scan.WithDefaultConventions(); //doesn't do it

    scan.With<MyScanner>();
  }
));

ObjectFactory.GetAllInstances<PersonBase>()
 .ToList()
  .ForEach(p => 
  { Console.WriteLine(p.FirstName); } );
Run Code Online (Sandbox Code Playgroud)

  • 您无需创建自己的扫描仪.在"扫描"表达式中,对PersonBase使用AddAllTypesOf.http://structuremap.net/structuremap/ScanningAssemblies.htm#section5 (3认同)