如何在Structuremap中使用自动注册和类型扫描

时间:2014-12-19 17:46:24

标签: c# structuremap structuremap3

在我的解决方案中,我有三个这样的项目。 enter image description here

我将Common.dll和Service.dll复制到d:\ libs这样的文件夹中,并将以下代码用于扫描类型

 ObjectFactory.Initialize(x =>
           {
              x.Scan(xx =>
               {
                   xx.AssembliesFromPath(@"d:\libs");
                   xx.LookForRegistries();
               });
           });
//I have PersonService that implement IPersonService
namespace Common
{
    public interface IPersonService
    {
        string SayHello(string name);
    }
}
namespace Services
{
    public class PersonService : IPersonService
    {
        public string SayHello(string name)
        {
            return string.Format("Hello {0}", name);
        }
    }
}

当我想从IPerson获取实例时初始化我的依赖项后,我收到此错误

  var personService = ObjectFactory.GetInstance<IPersonService>();
  

{&#34;没有注册默认实例,无法自动确定类型&#39; Common.IPersonService&#39; \ r \ n \ r \ n \ n没有为Common.IPersonService指定配置\ r \ n \ r \ n1。)Container.GetInstance(Common.IPersonService)\ r \ n&#34;}

3 个答案:

答案 0 :(得分:2)

  • 同时添加xx.WithDefaultConventions();
  • 当您使用StructureMap设计插件系统时,主机项目不应该引用任何插件。只应引用接口/合约插件,并且不应将此程序集复制到d:\libs文件夹。换句话说,当前的应用程序域不应该有任何程序集的2个实例。因此,如果您想直接在主机程序中使用IPersonService界面,请添加对Common.dll的引用,并且不要将其复制到d:\libs文件夹以避免重复。现在主持人项目也不应该引用Services.dll

答案 1 :(得分:1)

您可以在WithDefaultConventions()的来电中使用ScanDefaultConventionScanner会在内部使用var interfaceName = "I" + concreteType.Name; return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);

您可以阅读源代码或查看文档,但它会这样做:

IFooService

在默认约定扫描期间,扫描的每个具体类型将查找以字母“I”开头的类名的第一个接口。因此,在扫描过程中,FooService会在扫描过程中找到For<IFooService>().Use<FooService>()时自动注册并分配,因此您无需明确说明

{{1}}

当您没有为您请求的类型注册具体实现时,将始终抛出您看到的异常。

答案 2 :(得分:0)

您希望注册的类型不是因为您正在使用 xx.LookForRegistries()查找StructureMap注册表(您可以在此处阅读有关注册表的更多信息 - http://structuremap.github.io/registration/registry-dsl/)。如果您使用适当的注册创建此类注册表,那么SM将找到它们并注册。

如前所述,altrernative是使用 xx.WithDefaultConventions()。使用默认约定时,请查看此边缘情况,未注册预期类型 - https://stackoverflow.com/a/27449018/4336786