如何为这种情况编写StructureMap扫描仪

时间:2010-02-25 21:06:19

标签: c# structuremap

我在注册表中有这些注册,并试图找出使用扫描仪而不是手动注册来实现它们的正确方法。

For<ISomeView>.Use(HttpContext.Current.CurrentHandler)
For<IOtherView>.Use(HttpContext.Current.CurrentHandler)
For<IAnotherView>.Use(HttpContext.Current.CurrentHandler)

等等。我有一个IView固有的接口用作标记接口。

我最初的尝试看起来像这样

public void Process(Type type, Registry registry)
{
    Type _pluginType = typeof(IView);

    if (type.CanBeCastTo(_pluginType) && type.IsInterface)
    {
        string name = type.Name;
        registry.AddType(_pluginType, type, name);

        registry.For(_pluginType).Use(HttpContext.Current.CurrentHandler);
    }    
} 

然而,这导致我的物理ASP.NET页面被注册为自己。这是我从WhatDoIHave()

获得的
the_page_aspx (ASP.the_page_aspx) - 36d0cdb2-7118-4a1d-94a0-8de1b5ddc357 - 
Configured Instance of ASP.the_page_aspx, App_Web_4q8pukge, Version...

编辑为了回应KevM的评论,我想要实现的是任何时候StructureMap需要注入任何一个我的IView,它通过返回HttpContext.Current.CurrentHandler

来解决它

因此,如果我致电ObjectFactory.Resolve<ISomeView>(),我会得到(ISomeView)HttpContext.Current.CurrentHandler

如果我的构造函数为SomePresenter(IListView listView, IEditView editView),那么这些构造函数将被解析为(IListView)HttpContext.Current.CurrentHandler(IEditView)HttpContext.Current.CurrentHandler

我可以使用许多For<>.Use()语句执行此操作,如我的示例中所示,这意味着我应该能够使用扫描程序实现它,而不需要手动显式注册每个语句。如果命名约定有助于编写扫描程序,我的界面将始终命名为I_____View。我只是不确定我在上面的Process()方法的if语句中需要使用什么。

更新:根据@KevM的回答,它指出了我正确的方向

public class ViewScanner : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (type.IsA<IView>() && !type.IsConcrete())
        {
            registry.For(type).Use(c => HttpContext.Current.CurrentHandler);
        }
    }
}

(IsA&lt;&gt;只是IsAssignableFrom的扩展,因为对我而言,它的使用感觉倒退了)

1 个答案:

答案 0 :(得分:1)

我希望这接近你所寻找的。

public interface IView { }
public class View : IView { }
public class View2 : IView { }

public static class IckyStaticMonster
{
    public static IView Current { get; set;}
}

[TestFixture]
public class configuring_concrete_types
{
    [Test]
    public void TEST()
    {
        var container = new Container(cfg =>
        {
            cfg.Scan(scan =>
            {
                scan.TheCallingAssembly();
                scan.Convention<ViewScanner>();
            });
        });

        var current = new View2();
        IckyStaticMonster.Current = current;

        var view2 = container.GetInstance<View2>();

        view2.ShouldBeTheSameAs(current);
    }
}

public class ViewScanner : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        Type _pluginType = typeof (IView);

        if (_pluginType.IsAssignableFrom(type) && _pluginType.IsInterface)
        {
            registry.For(type).Use(c=>IckyStaticMonster.Current);
        }
    }
}