2010-10-15 104 views
3

在配置StructureMap容器​​时是否可以将请求类型作为参数传递。StructureMap获取请求类型

例如:

  container.Configure(x => { 
       x.For<ILogger>().Use(new TestLogger(log.Add, requestingType));   
      }); 

人请求类型为消费对象的类型:

public class SomeClass 
{ 
    private readonly ILogger logger; 
    public SomeClass(ILogger logger) 
    { 
     this.logger = logger; 
    } 
} 

所以传递到记录器的类型将是SomeNamespace.SomeClass。

感谢, 本

回答

3

您可以轻松地通过使用StructureMap的IContext访问请求的类型。

ObjectFactory.Configure(
    x => { 
     x.For<ILogger>().Use(context => new TestLogger(context.ParentType)); 
    }); 

在上述语句中,context.ParentType返回由StructureMap创建的类型。

杰里米米勒在博客文章中也介绍了这个话题。本文使用过时的语法,但它仍然是相关的:http://codebetter.com/jeremymiller/2009/01/15/using-the-build-session-in-structuremap/

如果您想检查所有在IContext可用的属性,你可以使用匿名函数,并设置一个断点在回行,像这样:

ObjectFactory.Configure(
    x => { 
     x.For<ILogger>() 
       .Use(context => 
       { 
        // Set breakpoint here and inspect the context 
        return new TestLogger(context.ParentType); 
       }); 
    }); 

更新:

确保使用.AlwaysUnique()(这相当于.CacheBy的较旧的语法(InstanceScope.Unique)),否则将StructureMap缓存ILogger的第一次请求这将导致原来的记录器bein g在单个GetInstance()调用期间被注入到ILogger的所有后续请求中。

如果已经嵌套在每个需要ILogger所以对于ObjectFactory.GetInstance < ISomeClass>(一个请求类)这可以容易地发生将导致ILogger被用于在层次结构中的最深的类创建,然后所有其他类将收到相同的ILogger实例,这很可能是你要做的不是想要发生。

因此,采取这种更新和Ben的小费考虑,这里有一个更好的解决方案:

x.For<ILogger>() 
    .AlwaysUnique() 
    .Use(c => new TestLogger(c.ParentType ?? c.BuildStack.Current.ConcreteType)); 
+1

谢谢,解决了这一段时间后,但忘了我曾问过。我发现'ctx.ParentType'有时返回null,所以做到以下几点:'对于()。使用(ctx => new TestLogger(ctx.ParentType ?? ctx.BuildStack.Current.ConcreteType));' – 2012-07-24 09:43:41

+0

@BenFoster谢谢为小费。经过测试,我确实看到了这种情况。另外,我注意到StructureMap没有为ObjectFactory.GetInstance()的一次调用的层次结构中需要的每个ILogger获取一个新的ILogger,所以在查看了一下后,我发现使用.AlwaysUnique()方法可以删除所有的缓存行为并给出期望的结果。我已经更新了我的答案,以反映我的发现和提示。谢谢。 – 2012-07-24 18:25:09

0

我找到了解决办法here

基本上我们改变了ILogger接口ILogger<T>并利用在StructureMap泛型类型推理功能。

严格地说,这并不回答我是否可以得到请求类型的问题,所以如果你知道如何做到这一点,请回复 - 这将是有益的知道。

0

首先,我想指出一个潜在的问题,使用Use(new Type())注册一个实例会导致该实例被注册为一个单例。为了避免这种情况,你可以使用(()=> new Type())。

这里是你如何在配置时获得请求的类型:

container.Configure(x => { 
    x.For<ILogger>().Use(c => new TestLogger(log.Add, c.Root.RequestedType)); 
}); 
+0

这将返回该实例的类型创建的,不是那种请求实例。例如,从MVC控制器请求一个ILogger,应该传递控制器的类型。希望澄清。 – 2010-10-15 21:59:08

+0

啊我明白了,这样做更有意义。我不知道在StructureMap中做这件事的方法。 – 2010-10-18 15:53:19

+0

解决方案不再有效; IContext.Root不存在于StructureMap 3.0 – Anthony 2014-07-10 11:57:50