Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923

Ищу удобный подход

18.05.2022, 22:35. Показов 2237. Ответов 30
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уткнулся в дно.

Тема приложения:
Messanger

Дано:
gRPC проект, View проект, прослойка между ними.
View ничего не знает о том, откуда и как поступают данные, об этом знает "прослойка".

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

Расписал интерфейс конечного результата:
C#
1
2
3
4
5
6
7
8
9
    public interface IMessageService
    {
        event EventHandler<NotifyDictionaryChangedEventArgs<Guid, MessageDto>> MessagesChanged;
 
        IReadOnlyDictionary<Guid, MessageDto> Messages { get; }
 
        void SendMessage(Guid guid, string username, string message);
        Task SendMessageAsync(Guid guid, string username, string message);
    }
Далее я реализовал абстрактный класс, дабы не повторять код.

Поднимаю событие, если список сообщений изменился.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    internal abstract partial class MessageServiceAbstract : IMessageService
    {
        public event EventHandler<NotifyDictionaryChangedEventArgs<Guid, MessageDto>> MessagesChanged;
 
        private int messagesChangedSyncNumber = 0;
 
        protected void RaiseMessagesChangedEvent(NotifyDictionaryChangedAction action, MessageDto newMessage = null, MessageDto oldMessage = null)
        {
            // ...
        }
 
        protected void RaiseMessagesChangedEvent(IDictionary<Guid, MessageDto> newElements)
        {
            // ...
        }
    }
Сам, собственно, список сообщений:
C#
1
2
3
4
5
6
7
8
9
10
11
    internal abstract partial class MessageServiceAbstract
    {
        private readonly Dictionary<Guid, MessageDto> messages = new Dictionary<Guid, MessageDto>();
 
        public IReadOnlyDictionary<Guid, MessageDto> Messages { get; }
 
        public MessageServiceAbstract()
        {
            Messages = new ReadOnlyDictionary<Guid, MessageDto>(messages);
        }
    }
И абстрактные методы
C#
1
2
3
4
5
6
    internal abstract partial class MessageServiceAbstract : IMessageService
    {
        public abstract void SendMessage(Guid guid, string username, string message);
 
        public abstract Task SendMessageAsync(Guid guid, string username, string message);
    }
Я сделал всё internal, дабы конечный потребитель не знал про абстрактный класс, ему он, думаю, ни к чему.

Далее я создал реализацию, непосредственно, под gRPC
C#
1
2
3
4
    internal class MessageServiceGrpc : MessageServiceAbstract, IMessageService
    {
        // ...
    }
Описание проблемы:
Как видите, мне пришлось сделать MessageServiceGrpc тоже internal, так как мой абстрактный класс -- internal.
В итоге я не понимаю как вывести мне тип "наружу". То есть кривая архитектура получается.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.05.2022, 22:35
Ответы с готовыми решениями:

UI на Unity. Какой подход для создания UI самый правильный и удобный в плане поддержки, внесения изменений и развития?
1. Как я понял, есть возможность рисовать UI на шейдерах и с помощью мешей (я пока мало что об этом всём знаю, так что вопрос может быть...

Ищу удобный и минималистичный движок новостей на подобии Data Life
Лучше бесплатный, с удобной системой комментариев

Ищу удобный и простой шаблон для создания интернет-магазина компьютеров
Скиньте сюда названия пожалуйста.)))

30
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16158 / 11278 / 2891
Регистрация: 21.04.2018
Сообщений: 33,164
Записей в блоге: 2
19.05.2022, 22:15
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от limeniye Посмотреть сообщение
ещё один абстрактный класс?)
Нет.
РЕАЛИЗАЦИЮ абстрактного.
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
19.05.2022, 23:36  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Для WPF проекта потом добавите свою реализацию абстрактного класса.
Элд Хасп, я не понимаю, зачем в WPF проекте реализовывать абстрактный класс. WPF -- это уровень View -- конечный потребитель, он получает лишь уже готовое.


Накидал то, как я это вижу.
1. Один проект WCF, другой gRPC -- это серверные части [ голубое ]

2. Далее проект с абстрактными типами для уровня модели и самим абстрактным классом [ красное ]

3. Один проект для реализации абстрактного класса под gRPC, другой проект для реализации абстрактного класса под WCF [ зелёное ]

4. Ну и дальше уже уровни View.

0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
19.05.2022, 23:42  [ТС]
Элд Хасп, показал как это выглядит с неймспейсами:
C#
1
2
AbstractMessanger.MessangerServiceAbstract service = new WCFMessangerModel.MessangerService();
AbstractMessanger.MessangerServiceAbstract service = new gRPCMessangerModel.MessangerService();
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16158 / 11278 / 2891
Регистрация: 21.04.2018
Сообщений: 33,164
Записей в блоге: 2
20.05.2022, 00:44
Цитата Сообщение от limeniye Посмотреть сообщение
3. Один проект для реализации абстрактного класса под gRPC, другой проект для реализации абстрактного класса под WCF [ зелёное ]
Да, всё верно.
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
20.05.2022, 10:09
Цитата Сообщение от limeniye Посмотреть сообщение
Ну и дальше уже уровни View.
А как вы планируете на стороне клиента (WPF, Console) абстрагировать локальную модель от конкретного протокола (WCF, gRPC)?
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
20.05.2022, 13:52  [ТС]
kotelok, через абстрактный класс.

Но объективно говоря я всё-таки сталкнулся с некоторыми трудностями.

Мне кажется, что могут случиться различия: например в gRPC проекте может быть на 1 метод больше.

Пока такой ситуации не возникло, но предположим, в gRPC классе мне нужно будет реализовать ещё 1 метод, допустим Initialize(); (условно). А в WСF такой метод не нужен (условно).

В таком случае, как первый вариант, я могу добавить ещё один абстрактный класс:
C#
1
2
3
4
public abstract MessangerServiceWithInitializeAbstract : MessangerServiceAbstract
{
    public abstract void Initialize();
}
Вариант второй:

Я могу добавить этот метод в сам MessangerServiceAbstract, но в WCF реализовать как NotImplemented.
0
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
20.05.2022, 14:50
Лучший ответ Сообщение было отмечено limeniye как решение

Решение

Цитата Сообщение от limeniye Посмотреть сообщение
NotImplemented
Скорее, это будет 'NotSupported'. Хотя, может это личные особенности восприятия, но 'NotImplemented' - это "ещё не успел, но надо", т.е. это для программиста исключение, которое не должно в проде возникать. А 'NotSupported' - именно "нет и не планировалось". Но да, это кривоватый вариант. Дополнительный промежуточный класс в этом случае будет более чисто выглядеть.

Цитата Сообщение от limeniye Посмотреть сообщение
через абстрактный класс
Т.е. на стороне клиентских приложений будут реализации для WCF и gRPC, которые будут реализовывать соответствующие методы взаимодействия с сервером?

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

Добавлено через 22 минуты
СЕРВЕР
Логика приложения реализуется на сервере, т.е. на сервере есть какой-то:
C#
1
2
3
4
5
6
7
8
9
10
11
12
public class SomeService : ISomeService
{
    public SomeDto GetSome(int id)
    {
        ....
    }
 
    public void CreateSome(SomeDto some)
    {
        ....
    }
}
Это именно БЛ приложения. Этот сервис понятия не имеет кто и как его будет использовать.

Поверх него реализованы внешние точки взаимодействия через:
1. REST.
2. gRPC.
3. WCF.

Которые для удобства могут оперировать теми же самыми 'SomeDto'. И задача которых - реализация специфики своего протокола для взаимодействия с внешними клиентами с последующим вызовом единой реализации 'SomeService' (в т.ч. интерпретация исключений от SomeService в специфичные для своего протокола пакеты/коды).
* в т.ч. их можно полностью кодогенерируемыми сделать.

КЛИЕНТ (тоже на C#, а значит может использовать ту же общую библиотеку DTO и интерфейсов)

Допустим, типовой WPF-клиент: View -> ViewModel -> Model.

И где-то на уровне 'Model' (или в частных случаях 'ViewModel') вам требуется сделать что-то типа:
C#
1
var someDto = _someService.GetSome(42);
И вот этот '_someService' - это реализаций того самого 'ISomeService' (из сборки, расшаренной на клиента и сервер). Но только под капотом не серверная реализация (т.е. не реальная бизнеслогика и обращение к хранилищу), а одна из клиентских реализаций (gRPC, WCF, REST), которая знает на какой адрес пойти и как отработать особенности конкретного протокола, чтобы на выходе клиентское приложение получило ожидаемый 'SomeDto'.
* в т.ч. их можно полностью кодогенерируемыми сделать.
1
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
20.05.2022, 14:52  [ТС]
kotelok, ну, по сути я это и нарисовал тут
Ищу удобный подход

У меня SomeDto и красном прямоугольнике, а вместо ISomeInterface — SomeAbstract, так как у меня есть общая реализация метода поднятия события

C#
1
2
3
4
5
6
7
protected void RaiseMessagesChanged(Action action, MessageDto newMessage, MessageDto oldMessage = null)
{
    if(action == Action.Add)
        messages.Add(newMessage);
 
    MessgaseChanged?.Invoke(...);
}
0
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
20.05.2022, 15:13
Я просто не уверен, что у нас одинаковое понимание этой картинки. Мне из неё не понятные зависимости сборок, местоположение бизнес-логики, разделение на клиентские и серверные сборки.

Хотя, вероятно, под вашу задачу именно ваш подход окажется более удобным.

Цитата Сообщение от limeniye Посмотреть сообщение
общая реализация метода поднятия события
Общая для клиента и сервера или общая для разных сервисов с бизнеслогикой на сервере?
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
20.05.2022, 17:30  [ТС]
kotelok, для клиента.

Допустим у вызвал метод await RemoveItemAsync(SomeTypeDto someObject); из ViewModel.

C#
1
2
3
4
5
6
7
8
9
10
private async Task RemoveItemAsync(SomeTypeDto someObject)
{
    var res = await _client.Remove(someObject.ToSomeType());
  
    if(res.IsSuccessful)
    {
        Items.Remove(someObject);
        RaiseItemsChanged(Action.Removed, someObject);
    }
}
0
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
20.05.2022, 18:06
Цитата Сообщение от limeniye Посмотреть сообщение
для клиента
Да, моя невнимательность. У вас вопрос по той части, которая реализуется именно на стороне клиентского приложения и задача которой максимально абстрагировать слой M/VM от нюансов конкретного протокола взаимодействия с сервером.

Тогда да, решение через абстрактные классы - один из вариантов, если есть общий функционал. И тогда тот случай, который вы описывали с недоступностью одного из методов в каком-то протоколе, придётся обходить именно через NotSupportedExeption, т.к. если выдать VM более узкоспециализированную абстракцию, то она в принципе не получит доступа к части функционала.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.05.2022, 18:06

Удобный ввод
Здравствуйте. Я иногда решаю задачи с codeforces.com, раньше я делал это на С++, а теперь решил попробовать на Java. Суть вот в чем: Нужно...

Удобный синопсис
Teamstudio ed.20, для R4-R6.x поставил себе на 8.5(Full ver), дайте ключики плиз. хотел поновее(26 версия), но не хочет...

Не удобный формат
Такая проблема, которую не могу решить. Есть выгрузка, ужасно сделанная и ничего не поделать. 1) Контакт: занимает целую строку и в ней...

Удобный ридер
Проникся такой идеей: написать программу, в которой будет книга. Как бы exe, а внутри него много текста. С чего стоит начать и на что...

удобный switch
Приветствую. Подскажите, можно ли использовать наподобие такой конструкции: switch ($some_var) { case 0, 5..9: //some actions; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Новости компьютерного мира и их обсуждение (4) Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru