Как написать сканер StructureMap для этого случая - PullRequest
2 голосов
/ 26 февраля 2010

У меня есть эти регистрации в реестре, и я пытаюсь найти правильный способ реализовать их с помощью сканера вместо ручной регистрации.

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, если соглашение о присвоении имен поможет при написании сканера. Я просто не уверен, что мне нужно использовать в приведенном выше операторе if для метода Process().

Обновление: С ответом @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 <> - это просто расширение для IsAssignableFrom, так как для меня его использование ощущается задом наперед)

1 Ответ

1 голос
/ 27 февраля 2010

Я надеюсь, что это близко к тому, что вы ищете.

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);
        }
    }
}
...