Связь слишком высока - как разработать этот класс лучше?

Мне нравится Flex Box , возможно, вы сможете работать в структуре, которая будет выглядеть примерно как


  
...some input fields

, а затем ваша CSS

.form{
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

центрирует все дочерние элементы в вашем .form div по вертикали и по горизонтали в .form без указания отступа или поля

8
задан Judah Gabriel Himango 9 October 2008 в 20:49
поделиться

5 ответов

Имейте классы, которые делают регистр работы для событий, они интересуются... шаблоном брокера события.

class EventBroker {
   private Dictionary<Type, Action<EventArgs>> messageHandlers;

   void Register<T>(Action<EventArgs> subscriber) where T:EventArgs {
      // may have to combine delegates if more than 1 listener
      messageHandlers[typeof(T)] = subscriber; 
   }

   void Send<T>(T e) where T:EventArgs {
      var d = messageHandlers[typeof(T)];
      if (d != null) {
         d(e);
      }
   }
}
15
ответ дан 5 December 2019 в 08:26
поделиться

Вы могли также использовать своего рода платформу МОК, как Spring.NET, для введения словаря. Таким образом, если Вы получаете новый тип сообщения, Вы не должны перекомпилировать этот центральный узел - просто изменяют файл конфигурации.


Долгий ожидаемый пример:

Создайте новое консольное приложение, названное Примером, и добавьте это:

using System;
using System.Collections.Generic;
using Spring.Context.Support;

namespace Example
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            MessageBroker broker = (MessageBroker) ContextRegistry.GetContext()["messageBroker"];
            broker.Dispatch(null, new Type1EventArgs());
            broker.Dispatch(null, new Type2EventArgs());
            broker.Dispatch(null, new EventArgs());
        }
    }

    public class MessageBroker
    {
        private Dictionary<Type, object> handlers;

        public Dictionary<Type, object> Handlers
        {
            get { return handlers; }
            set { handlers = value; }
        }

        public void Dispatch<T>(object sender, T e) where T : EventArgs
        {
            object entry;
            if (Handlers.TryGetValue(e.GetType(), out entry))
            {
                MessageHandler<T> handler = entry as MessageHandler<T>;
                if (handler != null)
                {
                    handler.HandleMessage(sender, e);
                }
                else
                {
                    //I'd log an error here
                    Console.WriteLine("The handler defined for event type '" + e.GetType().Name + "' doesn't implement the correct interface!");
                }
            }
            else
            {
                //I'd log a warning here
                Console.WriteLine("No handler defined for event type: " + e.GetType().Name);
            }
        }
    }

    public interface MessageHandler<T> where T : EventArgs
    {
        void HandleMessage(object sender, T message);
    }

    public class Type1MessageHandler : MessageHandler<Type1EventArgs>
    {
        public void HandleMessage(object sender, Type1EventArgs args)
        {
            Console.WriteLine("Type 1, " + args.ToString());
        }
    }

    public class Type2MessageHandler : MessageHandler<Type2EventArgs>
    {
        public void HandleMessage(object sender, Type2EventArgs args)
        {
            Console.WriteLine("Type 2, " + args.ToString());
        }
    }

    public class Type1EventArgs : EventArgs {}

    public class Type2EventArgs : EventArgs {}
}

И app.config файл:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
    </sectionGroup>
  </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects"/>
    </context>
    <objects xmlns="http://www.springframework.net">

      <object id="messageBroker" type="Example.MessageBroker, Example">
        <property name="handlers">
          <dictionary key-type="System.Type" value-type="object">
            <entry key="Example.Type1EventArgs, Example" value-ref="type1Handler"/>
            <entry key="Example.Type2EventArgs, Example" value-ref="type2Handler"/>
          </dictionary>
        </property>
      </object>
      <object id="type1Handler" type="Example.Type1MessageHandler, Example"/>
      <object id="type2Handler" type="Example.Type2MessageHandler, Example"/>
    </objects>
  </spring>
</configuration>

Вывод:

Type 1, Example.Type1EventArgs
Type 2, Example.Type2EventArgs
No handler defined for event type: EventArgs

Как видете, MessageBroker не знает ни об одном из обработчиков, и обработчики не знают о MessageBroker. Все отображение сделано в app.config файле, так, чтобы, если необходимо обработать новый тип события, можно было добавить его в файле конфигурации. Это особенно хорошо, если другие команды определяют типы событий и обработчики - они могут просто скомпилировать свой материал в dll, Вы бросаете его в свое развертывание и просто добавляете отображение.

Словарь имеет значения текстового объекта вместо MessageHandler<> потому что фактические обработчики не могут быть брошены к MessageHandler<EventArgs>, таким образом, я должен был бездельничать что немного. Я думаю, что решение является все еще чистым, и оно обрабатывает отображающиеся ошибки хорошо. Обратите внимание, что необходимо будет также сослаться на Spring.Core.dll в этом проекте. Можно найти библиотеки здесь и документацию здесь. Глава внедрения зависимости относится к этому. Также отметьте, нет никакой причины, необходимо использовать Spring.NET для этого - важная идея здесь является внедрением зависимости. Так или иначе что-то испытывает необходимость, чтобы сказать брокеру отправлять сообщения типа a к x и использует контейнер МОК для внедрения зависимости, хороший способ иметь брокера не, знают о x, и наоборот.

Некоторый другой ТАК вопрос, связанный с МОК и DI:

5
ответ дан 5 December 2019 в 08:26
поделиться

Я не вижу остальную часть Вашего кода, но я попробовал бы, создают намного меньшее количество классов аргумента События. Вместо этого создайте некоторых, которые подобны друг другу с точки зрения содержавших данных и/или способ, которым Вы обрабатываете их позже и добавляете поле, которое скажет Вам, какой точный тип события произошел (вероятно, необходимо использовать перечисление).

Идеально Вы не только сделали бы этого конструктора намного более читаемым, но также и способ, которым обрабатываются сообщения (сообщения группы, которые обрабатываются похожим способом в единственном обработчике событий),

0
ответ дан 5 December 2019 в 08:26
поделиться

Возможно, вместо того, чтобы иметь другой класс для каждого сообщения, используйте флаг, который определяет сообщение.

Это решительно сократило бы количество сообщений, Вы имеете и увеличиваете пригодность для обслуживания. Мое предположение - то, что большинство классов сообщений имеет о нулевом различии.

Трудно выбрать дополнительный способ напасть на это, потому что остальная часть архитектуры неизвестна (мне).

При рассмотрении Windows, например, он исходно не знает, как обработать каждое сообщение, которое могло бы быть разбросано. Вместо этого базовые обработчики сообщений регистрируют функции обратного вызова в основном потоке.

Вы могли бы проявить подобный подход. Каждый класс сообщений должен был бы знать, как обработать себя и мог зарегистрировать себя в объемном приложении. Это должно значительно упростить код и избавиться от плотного соединения.

0
ответ дан 5 December 2019 в 08:26
поделиться

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

Вы, кажется, используете систему типов для идентификации событий, в то время как она на самом деле предназначена для поддержки полиморфизма. Как Chris Lively предполагает, Вы могли точно также (не злоупотребляя системой типов), используют перечисление для идентификации сообщений.

Или можно охватить питание системы типов и создать объект Реестра, где каждый тип события регистрируется (статическим экземпляром, файлом конфигурации или безотносительно). Затем Вы могли использовать Цепочку шаблона Ответственности для нахождения надлежащего обработчика. Или обработчик делает обработку себя, или это может быть Фабрика, создав объект, который обрабатывает событие.

Последний метод смотрит немного underspecified и сверхспроектированный, но в случае 99 типов событий (уже), это кажется соответствующим мне.

0
ответ дан 5 December 2019 в 08:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: