Хобрук: Ваш путь к мастерству в программировании

Свободное автоматическое сопоставление NHibernate

Я просто бродил, можно ли использовать Fluent NHibernate для автоматического сопоставления объекта .Net TcpClient?

У меня есть класс со свойством TcpClient, которое я хотел бы отобразить.

Я попытался создать собственный класс tTcpClient, унаследованный от TcpClient, и добавить свойство Id с помощью метода получения / установки; однако он все еще искал поле Id для базового класса.

У кого-нибудь есть идеи, если это возможно, или мне нужно будет создать собственное сопоставление xml для TcpClient?

Я как бы надеялся, что смогу сохранить объект, чтобы легко воссоздать его при перезагрузке приложения и привязать свойства объекта TcpClient к PropertiesGrid и позволить настройку через это довольно легко.

Спасибо.


Ответы:


1

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

public class TcpClientMapper : IUserType {

    public SqlType[] SqlTypes {
        get {
            return new[] { 
                           new SqlType(DbType.String), 
                           new SqlType(DbType.Int32) 
                         };
        }
    }

    public Object NullSafeGet(IDataReader rs, String[] names, ...) {

        String address = NHibernateUtil.String.NullSafeGet(rs, names[0]);
        Int32 port = NHibernateUtil.Int32.NullSafeGet(rs, names[1]);

        return new TcpClient(address, port);
    }

    public void NullSafeSet(IDbCommand cmd, Object value, Int32 index) {
        TcpClient tcpClient = value as TcpClient;
        if(tcpClient == null) {
            NHibernateUtil.String.NullSafeSet(cmd, null, index);
            NHibernateUtil.Int32.NullSafeSet(cmd, null, index + 1);
        } else {
            EndPoint red = tcpClient.Client.RemoteEndPoint;
            IPEndPoint endpoint = ((IPEndPoint)red);
            NHibernateUtil.String.Set(cmd, endpoint.Address.ToString(), index);
            NHibernateUtil.Int32.Set(cmd, endpoint.Port, index + 1);
        }
    }

    public Type ReturnedType {
        get { return typeof(TcpClient); }
    }

    // TODO: implement other methods
}

И сопоставьте это вот так в hbm:

<property name="_tcpClient" type="MyNamespace.TcpClientMapper, MyAssembly">
    <column name="Address" />  <!-- NullSafeGet/Set index == 0 -->
    <column name="Port" />     <!-- NullSafeGet/Set index == 1 -->
</property>

Или используйте беглый UserTypeConvention:

public class TcpClientUserTypeConvention : UserTypeConvention<TcpClientMapper> {
}
09.09.2011
  • Я понимаю. Мне нужно будет реализовать все методы для IUserType, тогда я полагаю, чтобы он работал? Если да, то как бы вы применили для этого NullSafeSet? Само свойство в моем классе по-прежнему останется обычным правом TcpClient, или мне нужно будет изменить его на класс ClientMapper? 09.09.2011
  • Да, вам нужно реализовать все методы, это несложно, посмотрите ссылку в ответе. Свойство все равно останется обычным TcpClient (что немного странно с точки зрения дизайна). См. Последнее изменение для реализации NullSafeSet. 09.09.2011
  • Выглядит отлично, спасибо за помощь. Еще один быстрый вопрос? Как узнать порядок того, что отправляется в массив Strings []? Я понимаю, что вы читаете свойства, но как узнать, что адрес находится в позиции 0, а порт - в позиции 1 в массиве? Причина, по которой я спрашиваю, заключается в том, что я пытаюсь реализовать то же самое для последовательного соединения. 10.09.2011
  • См. Мое последнее изменение, столбцы перечислены в файле сопоставления, такой же порядок используется в реализации IUserType. 10.09.2011
  • И еще кое-что. После реализации этого, когда я пытаюсь сохранить объект с помощью ConnectionTCP, содержащего TcpClient, я получаю исключение {Не удалось преобразовать значение параметра из IPAddress в исключение Byte [].}. Я просмотрел NullSafeSet и, похоже, вытащил правильные значения. Есть предположения? 10.09.2011
  • Я говорил по поводу вызова функции NullSafeGet. Как узнать порядок, в котором свойства представлены вам в именах String []? 10.09.2011
  • См. Последнее изменение. Не удалось преобразовать значение параметра из IP-адреса в Byte []. + пояснение указателей 10.09.2011
  • Добавление сопоставления, как вы продемонстрировали выше, перечисление столбцов дает мне сопоставление свойств с неправильным количеством столбцов: Connections.ConnectionTCP.Client type: TcpClientMapper при вызове BuildSessionFactory. 12.09.2011
  • Кроме того, я не заметил, что не удалось преобразовать значение параметра из IPAddress в Byte [], о котором вы упомянули, но я предполагаю, что ваше исправление было вызвано вызовом .ToString () в конечной точке? 12.09.2011
  • @Натан. Ошибка, скорее всего, связана с тем, как вы реализовали IUserType. Смотрите последнее обновление. 12.09.2011
  • Понятно, поэтому в SqlType мне нужно было указать тип каждого свойства TcpClient. Спасибо большое, это очень помогло и было очень информативным. Теперь у меня есть интересная задача сделать то же самое для SerialPort. Мне просто нужно сделать то же самое, но добавить столбцы для всех параметров последовательного порта, которые мне нужны, чтобы создать последовательное соединение? 12.09.2011
  • Да, если вы хотите, чтобы SerialPort отображался как TcpClient. 12.09.2011

  • 2

    Натан,

    Вы видели этот проект?

    http://automapper.org/

    Ваше здоровье

    08.09.2011
  • Это должно работать как автоматическое отображение Fluent или что-то в этом роде? 10.09.2011
  • Я почти отклонил это как совершенно не по теме, но затем понял, что вы можете действительно использовать auto mapper как часть решения этой проблемы. Подробности напишу в ближайшее время. 10.09.2011
  • Начните с создания отдельного класса, содержащего все данные, которые вы хотите, чтобы NHibernate сохранял в базе данных. Затем используйте AutoMapper (инструмент для копирования данных из одного объекта в другой), чтобы переместить значения из вашего постоянного объекта в экземпляр TcpClient. 10.09.2011
  • Итак, если у меня есть класс ConnectionTCP со свойством TcpClient, я просто использую AutoMapper для сопоставления класса ConnectionTCP? Как получить из этого сопоставления NHibernate? 10.09.2011
  • Новые материалы

    Я собираюсь научить вас Python шаг за шагом
    Привет, уважаемый энтузиаст Python! 👋 Готовы погрузиться в мир Python? Сегодня я приготовил для вас кое-что интересное, что сделает ваше путешествие более приятным, чем шарик мороженого в..

    Альтернатива шаблону исходящих сообщений для архитектуры микросервисов
    Познакомьтесь с двухэтапным сообщением В этой статье предлагается альтернативный шаблон для папки Исходящие : двухэтапное сообщение. Он основан не на очереди сообщений, а на..

    React on Rails
    Основное приложение Reverb - это всеми любимый монолит Rails. Он отлично обслуживает наш API и уровень просмотра трафика. По мере роста мы добавляли больше интерактивных элементов..

    Что такое гибкие методологии разработки программного обеспечения
    Что представляют собой гибкие методологии разработки программного обеспечения в 2023 году Agile-методологии разработки программного обеспечения заключаются в следующем: И. Введение A...

    Ториго  — революция в игре Го
    Наш следующий вызов против ИИ и для ИИ. Сможет ли он победить людей в обновленной игре Го? Обратите внимание, что в следующей статье AI означает искусственный интеллект, а Goban  —..

    Простое развертывание моделей с помощью Mlflow — Упаковка классификатора обзоров продуктов NLP от HuggingFace
    Как сохранить свои модели машинного обучения в формате с открытым исходным кодом с помощью MLFlow, чтобы позже получить возможность легкого развертывания. Сегодня модели упаковки имеют несколько..

    Математика и интуиция - Часть 1
    У каждой математической формулы есть доказательство. Часто эти доказательства слишком сложно понять, поскольку многие из них основаны на индукции, некоторые - на очень сложных наблюдениях, а..