← Zurück

Классы и интерфейсы в S#

Михаил, я начал писать реализацию iTrader для S#, точнее пока только написал вроппер вокруг их библиотеки. И возникли некоторые вопросы по поводу дизайна базовых типов, а именно: почему Candle абстрактный, почему в itrader передаются не интерфейсы, а классы( например Candle а можно было сделать просто ICandle?). Вопросы эти возникли по следующей причине: Transaq Connector сделан по-дурацки он обменивается с программой неполноценными xml(зачем они эту ересь сделали не представляю-руки бы поотрывал тому кто это придумал). Поэтому я написал свои типы которые сериализуются и десериализуются. Встал вопрос совместимости с вашими типами. Унаследовать от Ваших классов не могу( мне же нужно сериализовать или десериализовать-а делаю это с помощью атрибутов). Были бы интерфейсы-никаких проблем. Эту проблему я конечно обойду-напишу преобразование типов. Но хочется чтобы пользователь имел доступ к дополнительным данным( ведь коннектор впринципе по некоторым полям передает больше значений). Итого: предлагаю Вам рассмотреть возможность использования только интерфейсов в iTrader. Тогда конкретная реализация зависела бы коннектора и могла учитывать какие-то его особенности или нести доп. поля.

War dieses Thema hilfreich?

Thema teilen

Kommentare (8)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Mikhail Sukhov
Mikhail Sukhov

Андрей Ефимов: почему Candle абстрактный,

Потому что это базовый класс. Обычно под счетчками подрузомевают временные. Для них как раз есть проивзодный от Candle класс - TimeFrameCandle.

Андрей Ефимов: почему в itrader передаются не интерфейсы, а классы( например Candle а можно было сделать просто ICandle?).

Там где нет реализации - использую интерфейсы. Там где есть - использую классы.

Андрей Ефимов: Transaq Connector сделан по-дурацки он обменивается с программой неполноценными xml(зачем они эту ересь сделали не представляю-руки бы поотрывал тому кто это придумал).

Товарщини изобрели веб сервис😀

Андрей Ефимов: Поэтому я написал свои типы которые сериализуются и десериализуются.

Ручками или какой-то спец механизм, аля XmlSerializer?

Андрей Ефимов: Встал вопрос совместимости с вашими типами. Унаследовать от Ваших классов не могу( мне же нужно сериализовать или десериализовать-а делаю это с помощью атрибутов). Были бы интерфейсы-никаких проблем. Эту проблему я конечно обойду-напишу преобразование типов. Но хочется чтобы пользователь имел доступ к дополнительным данным( ведь коннектор впринципе по некоторым полям передает больше значений).

Расскажите по подробнее о механизме сериализации и как это работает в транзаке. Попробую предложить решение.

Андрей Ефимов: Тогда конкретная реализация зависела бы коннектора и могла учитывать какие-то его особенности или нести доп. поля.

Доп поля записываются через ExtensionInfo

anothar
anothar Autor

Нет, боже упаси это делать ручками. Да через сериалайзер. Только сейчас пришла идея делать через xslt-тогда можно все привести к базовому классу. но уже поздно-код написан, да медленная это вещь. и не говорите- изобрели блин да не тем местом, колеса вдруг стали квадратными. один способо как с этим побороться я знаю-создать новый класс, производный от Вашего и написать в моем классе метод преобразования к этому классу, мне он не нравится тем что мне еще придется плодить классы, может у Вас есть предложение как это реализовать без создания еще новых классов? Тут основная проблема в том, что я не смогу переопределить сериализацию у Ваших типов( ну или это будет весьма геморно), точнее у их полей.

Mikhail Sukhov
Mikhail Sukhov

Андрей Ефимов: Нет, боже упаси это делать ручками. Да через сериалайзер.

Интересно, а что, там названия у нод и атрибутов любые могут быть? Или Вы поля у сущности назвали так же, как принято у Транзака? Если второе, то это не очень хорошо. Я раньше так же начинал с Квиком, делать десериализацию ДДЕ данных сразу в сущности. Потом такие траблы начались ввиде больших переделок на добавление нового поля.

Так что для себя я решил. Создание нового трейдера начинается с тотальной обертки АПИ. И эта обертка никак не использует типы S#. А сам трейдер лишь делает конвертацию данных туда и обратно.

Андрей Ефимов: Тут основная проблема в том, что я не смогу переопределить сериализацию у Ваших типов( ну или это будет весьма геморно), точнее у их полей.

Согласен. Я использую свою сериализацию на основе Ecng.Serialization. Отличается от стандартной тем, что можно контролировать процесс сериализации.

anothar
anothar Autor

Интересно, а что, там названия у нод и атрибутов любые могут быть? Название полей и атрибутов можно контролировать с помощью XmlElement/XmlAttribute. нет названия у меня более понятные. Если поле уж совсем корявое то я обычно делаю нормальное поле. кот не сериализую/десериализую и ПолеAsString кот и сериализуется/десериализуется. Согласен. Я использую свою сериализацию на основе Ecng.Serialization. Отличается от стандартной тем, что можно контролировать процесс сериализации. А можно поподробней. чем она отличается от стандартной? В стандартной можно контролировать названия полей с помощью атрибутов. На чем основана ваша собственная сериализация/десериализация? Так что для себя я решил. Создание нового трейдера начинается с тотальной обертки АПИ. И эта обертка никак не использует типы S#. Если были бы интерфейсы, а не классы то в моем случае можно было бы создать и на основе интерфейсов S#. Впринципе добавить еще одно поле при стандартной десериализации несложно.

Mikhail Sukhov
Mikhail Sukhov

Андрей Ефимов: А можно поподробней. чем она отличается от стандартной? В стандартной можно контролировать названия полей с помощью атрибутов. На чем основана ваша собственная сериализация/десериализация?

На метаданных (атрибуты или xml). Отличается наличием конвертеров. Например, сложные типы (картинки, шифрованные строчки, сетевые адреса) в xml так просто не запихать. Приходится создавать структуру только для сериализации, где такие типы упакованы в примитивный формат (строка, число). Ecng.Serialization использует конвертеры на поля. Он превращает сложный тип в простой при сериализации и наоборот.

И еще одно большое отличие - SerializatonItem. Это древовидная структура, которая содержит данные для записи в файл (или только то прочитанные из). Плюс в том, что эти данные можно потом передавать куда угодно. И записывать как угодно. Со стандартными сериализаторами такое не прокатит.

Пришлите мне какой-нить юз кейс из транзака и как Вы хотите его использовать с типом S#, а я вставлю код для работы через Ecng.Serialization.

anothar
anothar Autor

На метаданных (атрибуты или xml). Отличается наличием конвертеров. Например, сложные типы (картинки, шифрованные строчки, сетевые адреса) в xml так просто не запихать. Приходится создавать структуру только для сериализации, где такие типы упакованы в примитивный формат (строка, число). Ecng.Serialization использует конвертеры на поля. Он превращает сложный тип в простой при сериализации и наоборот. Вроде в стандартной сериализации можно реализовать свою сериализацию-то есть переопределить целиком. Но это как-то геморно. Я пробовал и не получилось, так что наверняка утверждать не буду. И еще одно большое отличие - SerializatonItem. Это древовидная структура, которая содержит данные для записи в файл (или только то прочитанные из). Плюс в том, что эти данные можно потом передавать куда угодно. И записывать как угодно. Со стандартными сериализаторами такое не прокатит. А это не аналог ли XmlDocument? Вот пример из моего кода:


[Serializable]
    public class ErrorCallback:ServerCallback
    {
        private static XmlSerializer _serializer = new XmlSerializer(typeof(ErrorCallback));

        [XmlElement("error")]
        public String Error
        {
            get;
            set;
        }

        public static ErrorCallback FromXmlString(String s)
        {
            s = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<ErrorCallback>"+s
                +"</ErrorCallback>";
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(s)))
            {
                return (ErrorCallback)_serializer.Deserialize(stream);

            }
        }
    }

Пока времени не было чтобы начать реализовать iTrader. Это пример прямо из кода использования стандартной десериализации для callback. для отправки команд я сериализую ручками( для десериализации бы это потребовало очень много времени). Вот пример xml ки которую должна парсить эта функция:


<error>Описание ошибки</error>

Напишите, пожалуйста, пример того как это будет выглядеть при Вашей десериализации.

Mikhail Sukhov
Mikhail Sukhov
  1. Стандартная сериализация позволяет контролировать только весь процесс в целом, а не какое-то отдельное поле. Да и реализовать интерфейс IXmlSerializable мягко говоря не для слабонервных.

public class ErrorInfo
{
   [Field("error")]
   public string Info { get; set; }
}

var ser = new XmlSerializer<ErrorInfo>();
ser.Deserialize(s);
  1. Вы в курсе, что атрибут Serializable никаким образом не относится к XmlSerializer?
anothar
anothar Autor

Спасибо, Михаил.

  1. Моих нервов не хватало.
  2. Выглядит проще обычной сериализации, потихоньку буду разбираться. Буду в дальнейшем пользоваться Вашей библиотекой, но пока оставлю свой код, ибо негоже просто так переделывать код.
  3. Нет. Но после Вашего вопроса вспомнил, что пару раз я это замечал. Я всегда путаюсь с XmlSerializer, BinaryFormatter и SoapFormatter. Почему-то в книгах чаще упоминают последние два😀