Установите внутреннюю зависимость по типу, используя Structuremap - PullRequest
0 голосов
/ 27 октября 2009

У меня есть конфигурация структуры карты, которая заставляет меня чесать голову. У меня есть конкретный класс, который требует интерфейсный элемент пользовательского интерфейса, который требует интерфейсный класс проверки. Я хочу, чтобы внешний конкретный класс получал элемент пользовательского интерфейса по умолчанию, но получал конкретный объект проверки для конкретного класса. Примерно так:

class MyView 
{
   IPrompt prompt
}

class GenericPrompt : IPrompt
{
   IValidator validator
}

class MyValidator : IValidator
{
   bool Validate() {}
}

Как я могу настроить structmap с DSL реестра, чтобы использовать MyValidator только при создании зависимостей для MyView. (И предположительно используя BobsValidator при создании зависимостей для BobsView)

1 Ответ

1 голос
/ 28 октября 2009

Получаете ли вы MyView (и BobsView) из контейнера? Можем ли мы предположить, что все они возьмут экземпляр IPrompt?

Одним из подходов будет регистрация всех ваших валидаторов с именем, которое совпадает с именами вашего представления. Вы могли бы реализовать свой собственный сканер типов, который просто удаляет суффикс Validator:

public class ValidatorScanner : ITypeScanner
{
    public void Process(Type type, PluginGraph graph)
    {
        if (!typeof (IValidator).IsAssignableFrom(type)) return;
        var validatorName = type.Name.Replace("Validator", "");
        graph.AddType(typeof(IValidator), type, validatorName);
    }
}

Теперь, если вы предполагаете, что IPrompt всегда будет запрашиваться представлением, которое следует соглашению об именах, ваш реестр может выглядеть следующим образом:

public class ValidatorRegistry : Registry
{
    public ValidatorRegistry()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.With<ValidatorScanner>();
        });

        ForRequestedType<IPrompt>().TheDefault.Is.ConstructedBy(ctx =>
        {
            var viewName = ctx.Root.RequestedType.Name.Replace("View", "");
            ctx.RegisterDefault(typeof(IValidator), ctx.GetInstance<IValidator>(viewName));
            return ctx.GetInstance<GenericPrompt>();
        });
    }
}

Чтобы получить представление с помощью соответствующего валидатора, вам необходимо запросить конкретный тип:

var view = container.GetInstance<MyView>();

Обратите внимание, что это будет работать только в том случае, если вы извлекаете представление с помощью прямого вызова контейнера (расположение службы), поскольку это зависит от "Root.RequestedType". В зависимости от того, как вы планируете получать свои представления, вы можете пройтись по BuildStack в поисках View (вместо того, чтобы предполагать, что это всегда Root).

...