Задать вопрос
Контакты

Достижения

Все достижения (7)

Наибольший вклад в теги

Все теги (95)

Лучшие ответы пользователя

Все ответы (260)
  • Какие есть инструменты для автоматического улучшения/рефакторинга кода в .NET приложениях?

    AlexanderYudakov
    @AlexanderYudakov
    C#, 1С, Android, TypeScript
    Есть. Деньги.
    Платишь их специалисту, клац, и все готово.
    Ответ написан
    Комментировать
  • Куда делась проблема замыканий в C#?

    AlexanderYudakov
    @AlexanderYudakov
    C#, 1С, Android, TypeScript
    Начиная с C# версии 5.0, переменные, объявленные в "foreach", считаются внутренними переменными цикла. Т.е. замыкания здесь больше нет.

    https://m.habr.com/post/141270/
    Ответ написан
    1 комментарий
  • Какую актуальную библиотеку можно использовать в роли брокера сообщений внутри .NET приложения?

    AlexanderYudakov
    @AlexanderYudakov
    C#, 1С, Android, TypeScript
    Решил размяться.

    Вот шина:
    MessageBus.cs

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace SimpleMessageBus
    {
        /// <summary>
        /// Рассылает события заинтересованным подписчикам
        /// в рамках одного приложения.
        /// </summary>
        /// <remarks>Используются WeakReference, чтобы не было утечек памяти
        /// на случай, если кто-то забудет отписаться. Поэтому не рекомендуется
        /// использовать лямбда-обработчики событий.</remarks>
        public static class MessageBus
        {
            private static readonly Dictionary<string, List<WeakReference<Action<string, object>>>> Subscribers =
                new Dictionary<string, List<WeakReference<Action<string, object>>>>();
    
            /// <summary>
            /// Оформляет подписку на событие
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="handler">Подписчик</param>
            public static void Subscribe(string topic,
                Action<string, object> handler)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                if (handler == null)
                    throw new ArgumentNullException(nameof(handler));
    
                List<WeakReference<Action<string, object>>> handlers;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out handlers))
                        handlers = Subscribers[topic] = new List<WeakReference<Action<string, object>>>();
    
                lock (handlers)
                    handlers.Add(new WeakReference<Action<string, object>>(handler));
            }
    
            /// <summary>
            /// Отменяет подписку на событие
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="handler">Подписчик</param>
            public static void Unsubscribe(string topic,
                Action<string, object> handler)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                if (handler == null)
                    throw new ArgumentNullException(nameof(handler));
    
                List<WeakReference<Action<string, object>>> list;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out list))
                        return;
    
                lock (list)
                {
                    var i = 0;
                    while (i < list.Count)
                    {
                        var reference = list[i];
                        if (!reference.TryGetTarget(out var target))
                            list.RemoveAt(i); // Заодно очищаем список от мертвых подписчиков
                        else if (target == handler)
                        {
                            list.RemoveAt(i);
                            return;
                        }
                    }
                }
            }
    
            /// <summary>
            /// Оповещает подписчиков о наступлении события
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="data">Данные события</param>
            public static void Publish(string topic, object data = null)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                List<WeakReference<Action<string, object>>> list;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out list))
                        return;
    
                var handlers = new List<Action<string, object>>();
                lock (list)
                {
                    var i = 0;
                    while (i < list.Count)
                    {
                        var reference = list[i];
                        if (!reference.TryGetTarget(out var target))
                            list.RemoveAt(i);
                        else
                        {
                            handlers.Add(target);
                            ++i;
                        }
                    }
                }
    
                // В Unity вызывать обработчики событий, наверное,
                // нужно как-то так:
                UnityEngine.WSA.Application.InvokeOnAppThread(() =>
                // А в обычном консольном приложении так:
                // Task.Run(() =>
                {
                    foreach (var handler in handlers)
                    {
                        try
                        {
                            handler.Invoke(topic, data);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex);
                        }
                    }
                }, false);
            }
        }
    }


    Вот пример использования:
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace SimpleMessageBus
    {
        public static class Program
        {
            public static async Task Main(string[] args)
            {
                Debug.WriteLine("Started.");
    
                MessageBus.Subscribe("Rain", RainHandler);
                MessageBus.Publish("Rain");
    
                await Task.Delay(100); // Ждем, пока событие поступит
                MessageBus.Unsubscribe("Rain", RainHandler);
                
                Debug.WriteLine("Finished.");
            }
    
            private static void RainHandler(string topic, object data)
            {
                Debug.WriteLine("Event: " + topic);
            }
        }
    }


    P.S. Бесплатно. Опенсорс.

    Upd. Добавил вызов UnityEngine.WSA.Application.InvokeOnAppThread() — все-таки у нас целевая платформа Unity.
    Ответ написан
    1 комментарий
  • Знаю Kotlin, не знаю Java. Возьмут ли на работу?

    AlexanderYudakov
    @AlexanderYudakov
    C#, 1С, Android, TypeScript
    Основной язык андроида, согласно официальной документации - Kotlin.
    https://developer.android.com/training/basics/firs...

    А чего там старые пердуны ворчат... да пусть ворчат, вам-то что :)
    Ответ написан
    4 комментария

Лучшие вопросы пользователя

Все вопросы (2)