DynamicData у .NET: спрощуємо управління реактивними даними

Я, Юрій Габа, Head of Software Development Competence Center у Vector Software. У сучасному світі застосунків зі складними потоками даних наша взаємодія з ними має бути не тільки швидкою, але й інтуїтивно зрозумілою. З DynamicData це не просто мрія, це реальність, яка доступна кожному розробнику .NET.

Мета цієї статті — надати всебічне розуміння DynamicData, її ключових концепцій та практичного застосування. Разом ми розглянемо основні аспекти цієї бібліотеки та її користь у розробці програмного забезпечення.

Що таке DynamicData?

DynamicData — бібліотека в екосистемі .NET, яка спрощує реактивне управління даними, полегшуючи роботу зі складними операціями. Вона побудована на принципах Reactive Extensions (Rx) і містить набір інструментів та розширень, які дозволяють розробникам реактивно управляти колекціями, тобто будь-які зміни в даних автоматично та ефективно поширюються по всьому застосунку.

Основні можливості DynamicData

  1. Об’єкти спостереження (Observables) для даних: DynamicData побудована на реактивних принципах — це означає, що вона надає об’єкти спостереження, які вносять зміни в колекції даних. На ці об’єкти можна легко підписатися, що дозволить вам реагувати на зміни у ваших даних.
  2. Автоматичні операції з даними. DynamicData обробляє загальні операції з даними, такі як фільтрація, сортування, групування та агрегація, зменшуючи потребу в шаблонному коді.
  3. Підтримка прив’язки до інтерфейсу користувача. DynamicData безпроблемно інтегрується з інтерфейсами користувача, такими як WPF, Xamarin та інші, полегшуючи прив’язку колекцій до елементів UI.
  4. Безпека потоків. Бібліотека забезпечує безпечні операції з потоками, що робить її придатною для застосунків зі складними вимогами до багатопотоковості.
  5. Ефективна обробка даних. DynamicData оптимізує обробку даних, забезпечуючи високу продуктивність навіть з великими та складними наборами даних.
  6. Кешування та запам’ятовування. DynamicData має можливості кешування в пам’яті та запам’ятовування, які допомагають зменшити необхідність повторного отримання або розрахунку даних. Це може значно покращити продуктивність вашого застосунку.
  7. Відстеження змін. Бібліотека дозволяє відстежувати зміни (додавання, оновлення та видалення) у вашій колекції даних. Це корисна фіча, коли вам потрібно знати, що змінилося у вашому дата-пулі, наприклад, для оновлення UI або управління оновленнями в реальному часі.
  8. Динамічні ланцюжки оновлень. Ви можете плавно та динамічно об’єднати кілька операцій зі своїми колекціями даних. Це дозволяє з легкістю створювати складні послідовності маніпуляцій даними.
  9. Керування пам’яттю. DynamicData розроблена з урахуванням управління пам’яттю. Бібліотека пропонує функції для обмеження використання пам’яті під час роботи з великими наборами даних.

Занурення в реактивні розширення (Rx)

Перш ніж занурюватися в те, як DynamicData використовує Rx, важливо зрозуміти основи самих Rx.

Розуміння реактивних розширень (Rx)

Реактивні розширення (Rx) — це бібліотека, яка компонує асинхронні та подійно-орієнтовані програми за допомогою спостережуваних послідовностей. Вона пропонує багатий словник для створення, поєднання, фільтрації та трансформації спостережуваних послідовностей.

За своєю суттю Rx вводить дві основні концепції: об’єкти спостереження та спостерігачі. Об’єкти спостереження випускають дані або сповіщення про події з часом, до яких підписуються спостерігачі, реагуючи на кожен випущений елемент.

IObservable<int> numberSequence = Observable.Range(1, 10);
numberSequence.Subscribe(number => Console.WriteLine(number));

Цей приклад Rx створює послідовність спостережуваних чисел від 1 до 10. Спостерігач потім слухає цю послідовність, друкуючи кожне число на консолі, коли воно отримується.

Використання Rx з DynamicData

У сфері сучасної розробки застосунків на .NET управління асинхронними потоками даних і реагування на зміни стану залишаються критичними викликами. Реактивні розширення (Rx) з їхньою потужною абстракцією асинхронних потоків даних через об’єкти спостереження змінюють підхід розробників до цих завдань.

Однак, коли застосовується реактивна парадигма до колекцій, Rx сам собою іноді може бути недостатнім. Тут на сцену виходить DynamicData, яка елегантно заповнює прогалину між реактивним програмуванням та управлінням динамічними колекціями даних.

DynamicData: розширення Rx для динамічних колекцій

DynamicData бере основні принципи Rx і розширює їх до області колекцій. Вона забезпечує набір інструментів та абстракцій для створення, управління та споживання колекцій, які реактивно змінюються з часом.

З DynamicData, колекції стають спостережуваними джерелами, які не тільки випускають елементи, але й повідомляють підписників про зміни в самій колекції — такі як додавання, видалення та оновлення.

var sourceList = new SourceList<int>();
sourceList.Connect()
          .Subscribe(changes => {
              foreach (var change in changes)
              {
                  Console.WriteLine($"Change: {change}");
              }
          });
sourceList.AddRange(new[] {1, 2, 3});
sourceList.Remove(2);

У цьому прикладі DynamicData створюється SourceList<int> як динамічне джерело даних. Викликаючи .Connect(), отримуємо об’єкт спостереження, що випускає сповіщення кожного разу, коли список змінюється. Підписка на цей об’єкт спостереження дозволяє нам реагувати на додавання та видалення, при цьому підписник друкує кожну зміну на консолі.

Синергія між Rx та DynamicData

DynamicData дозволяє застосовувати оператори запитів Rx безпосередньо до динамічних джерел даних. Ця синергія дозволяє чітко та лаконічно виражати складні сценарії маніпуляції та трансформації даних.

Наприклад, комбінуючи оператори Rx зі спостережуваними DynamicData, можна легко реалізувати фільтрацію, сортування та групування даних в реальному часі у відповідь на введення користувача або інші зовнішні події. Це робить її потужною для розробки застосунків зі складними, орієнтованими на дані інтерфейсами користувача, які потребують відображення змін основних даних у реальному часі.

sourceList.Connect()
          .Filter(item => item % 2 == 0)
          .Subscribe(evenNumbers => {
              Console.WriteLine("Even numbers:");
              foreach (var number in evenNumbers) Console.WriteLine(number);
          });
sourceList.AddRange(new[] {4, 5, 6});

Цей розширений приклад фільтрує sourceList, залишаючи лише парні числа, демонструючи, як оператори DynamicData та Rx можуть бути послідовно з’єднані для виконання складніших завдань обробки даних у реактивному режимі.

Оператори Rx у DynamicData

DynamicData переносить реактивну парадигму до управління колекціями в .NET, безперервно інтегруючись з реактивними розширеннями (Rx), що пропонує потужний набір інструментів для маніпуляції даними. Використання операторів Rx з колекціями DynamicData дозволяє розробникам виконувати складні запити, трансформації та агрегації в декларативній та виразній манері.

Сила операторів Rx

Цей розділ досліджує, як оператори Rx можуть бути застосовані для розширення можливостей DynamicData, спрощуючи управління динамічними потоками даних у застосунках.

Оператори Rx є основними елементами реактивного програмування в Rx. Вони можуть фільтрувати, вибирати, комбінувати та виконувати багато інших операцій над послідовностями даних. Коли вони застосовуються до реактивних колекцій DynamicData, ці оператори відкривають нові можливості для обробки даних у реальному часі та оновлень інтерфейсу користувача.

Застосування операторів Rx до колекцій DynamicData

Розгляньмо сценарій, де у нас є SourceList<T> цін акцій, і ми хочемо відфільтрувати цей список, щоб показати лише ті, ціна яких перевищує $100. Крім того, ми хочемо трансформувати отриманий список у формат, придатний для відображення в інтерфейсі користувача.

var stockPrices = new SourceList<Stock>();
stockPrices.Connect()
    .Filter(stock => stock.Price > 100)
    .Transform(stock => $"{stock.Name}: ${stock.Price}")
    .Subscribe(filteredStocks => {
        Console.WriteLine("High-value stocks:");
        foreach (var stock in filteredStocks) Console.WriteLine(stock);
    });
stockPrices.AddRange(new[] {
    new Stock("AAPL", 120),
    new Stock("GOOGL", 90),
    new Stock("MSFT", 110)
});

У цьому прикладі використовується Filter для спостереження лише за тими акціями, ціна яких перевищує $100, а Transform застосовується для перетворення даних у текстовий формат. Це поєднання операторів Rx дозволяє нам легко маніпулювати даними та споживати їх у спосіб, який підходить для оновлень UI у реальному часі.

DynamicData та Rx: синергетичний підхід

Інтеграція операторів Rx з колекціями DynamicData є свідченням гнучкості та потужності бібліотеки. Використовуючи набір операторів Rx, розробники можуть виконувати широкий спектр завдань з маніпулювання даними у динамічних колекціях: від простого фільтрування і трансформації до складніших операцій, таких як обмеження за часом (Throttle), пакування (Buffer) і поєднання декількох джерел даних (Merge, CombineLatest).

Розглянемо складніший приклад, де ми хочемо поєднати оновлення цін акцій з двох різних джерел і обмежити їх, щоб уникнути перевантаження користувацького інтерфейсу.

var source1 = new SourceList<Stock>();
var source2 = new SourceList<Stock>();
source1.Connect().Merge(source2.Connect())
    .Throttle(TimeSpan.FromSeconds(1))
    .Transform(stock => $"{stock.Name}: ${stock.Price}")
    .Subscribe(throttledUpdates => {
        Console.WriteLine("Throttled stock price updates:");
        foreach (var update in throttledUpdates) Console.WriteLine(update);
    });
source1.Add(new Stock("AAPL", 120));
source2.Add(new Stock("MSFT", 110));

У цьому прикладі оператор Merge об’єднує оновлення з двох джерел цін акцій, а Throttle забезпечує обробку оновлень не більше одного разу за секунду. Це демонструє, як DynamicData разом з операторами Rx можуть бути використані для ефективного управління потоками даних у реальному часі з високою продуктивністю.

Техніки розширеного маніпулювання даними з використанням DynamicData

DynamicData не лише спрощує спостереження та маніпулювання динамічними колекціями; вона також пропонує багатий набір інструментів для виконання розширених технік маніпулювання даними. Ці можливості дозволяють розробникам вирішувати складні завдання обробки даних, такі як агрегація, поєднання та динамічне оновлення потоків даних з легкістю.

У цьому розділі ми докладно розглянемо деякі з розширених технік, які можна використовувати в бібліотеці DynamicData, проілюструвавши їх потужність та гнучкість на практичних прикладах.

Перетворення та агрегування даних

Однією з ключових переваг DynamicData є її можливість динамічно перетворювати та агрегувати дані. Оператор Transform дозволяє розробникам застосовувати функцію перетворення до кожного елемента у колекції, ефективно проєктуючи кожен елемент у нову форму. Під час поєднанні з операторами агрегації, такими як Count, Sum або Group, це надає потужні можливості формування та узагальнення даних.

var sourceList = new SourceList<Employee>();
sourceList.Connect()
    .Transform(employee => new { employee.Name, employee.Department })
    .Group(employee => employee.Department)
    .Subscribe(groups => {
        foreach (var group in groups)
        {
            Console.WriteLine($"Department: {group.Key}, Employees: {group.List.Count}");
            foreach (var employee in group.List)
            {
                Console.WriteLine($" - {employee.Name}");
            }
        }
    });
sourceList.AddRange(new[]
{
    new Employee("Jane Doe", "IT"),
    new Employee("John Smith", "HR"),
    new Employee("Anne Brown", "IT")
});

У цьому прикладі співробітники спочатку перетворюються, щоб дані містили лише їхнє ім’я та відділ. Потім вони групуються за відділом, що демонструє, як агрегувати дані в значущі групи для подальшої обробки або відображення.

Комбінація динамічних даних

Комбінування даних з кількох джерел — ще одна сфера, в якій DynamicData відмінно справляється. Бібліотека надає кілька операторів для цієї цілі, таких як Merge, CombineLatest і Zip, кожен з яких служить різним випадкам використання комбінування даних.

Наприклад, CombineLatest може бути використаний, коли вам потрібно поєднати елементи з кількох джерел і отримати останнє значення з кожного джерела щоразу, коли будь-яке джерело випускає елемент.

var source1 = new SourceList<int>();
var source2 = new SourceList<int>();
source1.Connect().CombineLatest(source2.Connect())
    .Subscribe(combination => {
        Console.WriteLine($"Latest Combination: {combination.Item1}, {combination.Item2}");
    });
source1.Add(1);
source2.Add(2);
source1.Add(3);

Цей код призводить до виведення комбінованих останніх елементів з обох джерел щоразу, коли будь-яке з них випускає елемент, демонструючи динамічний спосіб роботи з кількома потоками даних.

Реакція на зміни властивостей

Розширене маніпулювання даними в DynamicData не обмежується лише роботою з колекціями. Оператор AutoRefresh дозволяє розробникам автоматично спрацьовувати оновлення, коли змінюється властивість об’єкта у колекції. Це особливо корисно для сценаріїв інтерфейсу користувача, де інтерфейс повинен реагувати на зміни у моделях даних.

var sourceList = new SourceList<Product>();
sourceList.Connect()
    .AutoRefresh(product => product.Price)
    .Filter(product => product.Price > 100)
    .Subscribe(filtered => {
        Console.WriteLine("Products with price > $100:");
        foreach (var product in filtered) Console.WriteLine($"{product.Name} - ${product.Price}");
    });
var product = new Product("Laptop", 90);
sourceList.Add(product);
product.Price = 150; // Triggers AutoRefresh and subsequently the Filter operator.

У цьому прикладі оператор AutoRefresh відстежує зміни властивості Price. Коли ціна продукту змінюється таким чином, що вона відповідає критеріям фільтрації, підписник отримує повідомлення, що дозволяє застосунку реагувати в реальному часі на зміни в основних даних.

Оптимізація продуктивності та кращі практики з використанням DynamicData

Ефективне керування даними є критично важливим для продуктивності та масштабованості застосунків .NET, особливо тих, які мають справу з великими наборами даних або вимагають реального часу відгуку. DynamicData, завдяки своєму багатому набору функцій для управління динамічними колекціями, пропонує безліч можливостей для оптимізації продуктивності.

Однак, щоб повністю використовувати ці можливості, розробники повинні бути уважними до найкращих практик і поширених помилок. Цей розділ наводить ключові стратегії для оптимізації використання DynamicData, забезпечуючи, що застосунки залишаються продуктивними та реактивними.

Ефективне керування підписками

Реактивний характер DynamicData обертається навколо концепції, де споживачі підписуються на джерела даних, щоб реагувати на зміни. Хоча це потужно, неправильне керування підписками може призвести до витоку пам’яті та погіршення продуктивності.

  • Утилізація підписок: завжди переконуйтеся, що підписки утилізуються, коли вони більше не потрібні. Використання методу розширення DisposeWith може спростити цей процес, прив’язавши життєвий цикл підписок до CompositeDisposable, який можна утилізувати одним махом.
var disposables = new CompositeDisposable();
sourceList.Connect()
    .Transform(item => TransformItem(item))
    .Subscribe(transformed => HandleTransformed(transformed))
    .DisposeWith(disposables);
// When done, dispose of all subscriptions at once
disposables.Dispose();
  • Використовуйте WhenPropertyChanged для точного спостереження за змінами властивостей. Замість підписки на всі об’єкти для отримання змін, використовуйте WhenPropertyChanged, щоб спостерігати за змінами конкретних властивостей — це дозволяє зменшити непотрібні сповіщення.

Оптимізація обробки даних

DynamicData пропонує безліч операторів для опитування та маніпулювання потоками даних. Ефективне використання цих операторів може значно вплинути на продуктивність застосунку.

  • Відкладення обробки даних. Використовуйте оператори Defer та DeferUntilLoaded, щоб відкласти обробку до повного заповнення колекції або до виникнення значних змін. Це дозволяє зменшити накладні витрати обробки кожного елемента окремо під час масового оновлення.
sourceList.Connect()
    .DeferUntilLoaded()
    .Subscribe(changeSet => ProcessChangeSet(changeSet));
  • Мінімізація оновлень інтерфейсу користувача. Обмежуйте оновлення інтерфейсу користувача, щоб запобігти перевантаженню процесу відтворення, особливо в реальному часі. Оператор Throttle можна використати для обмеження швидкості оновлень.
sourceList.Connect()
    .Throttle(TimeSpan.FromMilliseconds(500))
    .ObserveOnDispatcher() // Ensure UI updates happen on the UI thread
    .Bind(out var boundCollection) // Bind to a UI-friendly collection
    .Subscribe();

Управління пам’яттю та ресурсами

Управління пам’яттю та ресурсами є важливим аспектом під час роботи з великими наборами даних у DynamicData. Обмеження розміру буферів є одним зі способів зменшення використання пам’яті:

  • Обмежуйте розмір буферів: При використанні операторів, таких як Buffer або Window, обмежуйте розмір буферів, щоб уникнути надмірного використання пам’яті.
sourceList.Connect()
    .Buffer(TimeSpan.FromSeconds(1), 100) // Buffer items for 1 second or 100 items, whichever comes first
    .Subscribe(buffer => ProcessBuffer(buffer));
  • Використовуйте Virtualization для великих наборів даних. Під час відображення даних в інтерфейсі користувача, особливо з фреймворками, такими як WPF або Xamarin.Forms, використовуйте техніки віртуалізації, щоб рендерити лише видимі елементи, зменшуючи вимоги до пам’яті та обробки.

Найкращі практики для маніпулювання даними

  • Віддавайте перевагу незмінним (Immutable) моделям даних. Де це можливо, використовуйте незмінні об’єкти, щоб зменшити складність і непередбачені побічні ефекти, що полегшує розуміння стану застосунку.
  • Оптимізуйте ланцюжки обробки даних. Ретельно розгляньте порядок та типи використовуваних операторів. Наприклад, розміщення оператора Filter перед оператором Transform зменшує робоче навантаження, виконуючи трансформацію лише для елементів, які відповідають критеріям фільтрації.

Використання DynamicData у реальному житті

Реактивна модель програмування DynamicData надає надійне рішення для управління складними та динамічними даними в різних застосунках .NET. Від фінансових панелей, що відображають дані в реальному часі, до складних інтерфейсів користувача у системах охорони здоров’я, DynamicData виявляється корисним інструментом.

Цей розділ досліджує кілька сценаріїв використання в реальному світі, ілюструючи гнучкість та потужність бібліотеки в розв’язання реальних проблем.

Real-Time Financial Dashboards

Сценарій. Фінансова компанія потребувала розробити панель керування, яка може відображати дані фондового ринку в реальному часі, включно з цінами, тенденціями та сповіщеннями. Потрібно було обробляти високочастотні оновлення з кількох джерел та презентувати дані у легкому для засвоєння форматі для трейдерів та аналітиків.

Рішення. Завдяки використанню DynamicData, компанія змогла агрегувати потоки живих даних в єдину, реактивну модель даних. Використовуючи SourceCache<T, TKey> для керування колекцією даних про акції, вони реалізували динамічне фільтрування, сортування та агрегацію для відображення даних в реальному часі. Оператори Connect, Bind та Throttle використовувалися для ефективного оновлення інтерфейсу користувача без перевантаження головного потоку інтерфейсу або кінцевих користувачів занадто великою кількістю інформації одночасно.

Результат. Отримана програма надала користувачам дуже реактивну, реально-часову панель керування, яка могла миттєво адаптуватися до змін на ринку. Ефективна обробка даних та зв’язування інтерфейсу користувача в DynamicData значно зменшили затримку між рухами на ринку та оновленнями панелі керування, що дозволило приймати вчасні рішення.

Healthcare Patient Monitoring System

Сценарій. Компанія з технологій у галузі охорони здоров’я розробила систему моніторингу пацієнтів для лікарень. Система повинна відстежувати та відображати в реальному часі основні показники здоров’я для кількох пацієнтів одночасно та сповіщати медичний персонал про будь-які критичні зміни у стані пацієнта.

Рішення. Використовуючи DynamicData, бекенд системи агрегував інформацію з різних медичних пристроїв та датчиків в SourceList<T> для кожного пацієнта. Застосовуючи оператор AutoRefresh, система реактивно реагувала на зміни в даних пацієнта. Це налаштування дозволило реалізувати складну логіку для виявлення критичних станів та спрацювання тривог. На фронтенді DynamicData сприяла безперешкодному зв’язуванню даних з інтерфейсом користувача, що гарантувало точне та оперативне відображення даних пацієнта на екранах моніторингу.

Результат. Система моніторингу пацієнтів отримала високі оцінки за надійність та реактивність. Реактивні колекції DynamicData забезпечували оновлення інтерфейсу користувача останніми даними пацієнта, що дозволило медичному персоналу швидко реагувати на надзвичайні ситуації. Здатність системи ефективно обробляти дані в реальному часі зробила її надкорисним інструментом у наборі засобів догляду за пацієнтами у лікарнях.

E-Commerce Inventory Management

Сценарій. Електронна торгова платформа потребує рішення для управління рівнями запасів тисяч продуктів в реальному часі. Завданням було негайно відображати зміни в запасах по всій платформі, щоб уникнути проблем замовлень і надавати аналітику про тенденції у запасах.

Рішення. Платформа використала DynamicData для обробки даних про запаси, використовуючи SourceCache<T, TKey> для підтримки реактивного списку запасів. Оновлення запасів, отримані зі складських і систем продажів, об’єднувалися в потік запасів за допомогою оператора Merge. Цей підхід дозволяв оновлювати рівні запасів в реальному часі, які потім динамічно зв’язувалися з інтерфейсом користувача торгової платформи та інформаційно-аналітичною панеллю.

Результат. Використання DynamicData дозволило в реальному часі синхронізувати дані про запаси по всій електронній торговій платформі, зменшуючи випадки відсутності на складі або перепродажу. Крім того, команді аналітики вдалося використовувати ті ж потоки даних для отримання в реальному часі інсайтів щодо тенденцій у запасах, що допомогло під час прийняття стратегічних рішень.

Особистий досвід: Real-time Maritime Monitoring

На проєкті, спрямованому на морський моніторинг в реальному часу, ми успішно використовували DynamicData разом з Reactive Extensions (Rx) для управління та обробки даних для систем оптимізації та нагляду за морськими об’єктами.

Використання SourceCache<T, Key> дозволило нам ефективно зберігати колекції офшорних об’єктів у динамічних потоках даних, забезпечуючи одночасні оновлення даних для кількох кінцевих користувачів. Це дало динамічну маніпуляцію даними, дозволяючи користувачам реагувати на конкретні морські події або їх генерування.

Ми застосували два підходи до об’єднання даних з різних джерел в єдиний кеш, використовуючи оператори Merge Rx та Join DynamicData, що підкреслює гнучкість бібліотеки у роботі з різними типами об’єктів та зв’язками. Зокрема, оператор LeftJoinMany використовувався для ефективного управління даними, що стосуються морських об’єктів та пов’язаних подій, як-от попередження.

Крім того, проєкт продемонстрував можливість DynamicData покращувати реагування інтерфейсу користувача за допомогою операторів, як-от AutoRefresh та Bind, забезпечуючи оновлення елементів інтерфейсу у реальному часі на основі зміни даних. Це було критично важливо для моніторингу морської діяльності та реагування на події вчасно. Використання DisposeMany забезпечило оптимальне управління ресурсами, зберігаючи реагування системи навіть серед обробки великого потоку даних.

Цей досвід підкреслює масштабованість та гнучкість DynamicData в реальних сценаріях, надаючи надійне рішення для складних викликів управління даними в реальному часі.

Висновок

DynamicData в .NET змінює парадигму у тому, як ми керуємося та реагуємо на зміни даних у наших застосунках. Абстрагуючи складність синхронізації даних та надаючи набір інструментів для реактивного керування даними, вона надає розробникам можливість створювати більш ефективні та підтримувані застосунки. Оскільки цифровий ландшафт продовжує еволюціювати в бік більш динамічних та даними інтенсивних застосунків, прийняття бібліотек, подібних до DynamicData, є перевагою та необхідністю.

Незалежно від того, чи ви новачок у реактивному програмуванні, чи ви хочете удосконалити свої наявні застосунки, DynamicData надає як фундаментальні, так і високорівневі можливості для підняття ваших .NET-проєктів на новий рівень. Я закликаю вас дослідити DynamicData, вивчити його широку документацію та приєднатися до живої спільноти розробників, які трансформують наше сприйняття та взаємодію з даними в .NET.

Поки ми продовжуємо встановлювати нові рекорди у розробці застосунків, дозвольте DynamicData стати ключовим інструментом у вашому наборі інструментів розробника. Прийміть реактивну парадигму, сприяйте екосистемі та разом будуємо майбутнє .NET-застосунків.

Корисні посилання

  1. Офіційний вебсайт DynamicData. Для прямого та комплексного ресурсу з DynamicData відвідайте офіційний вебсайт. Тут надається детальна документація, уроки та приклади, спеціально зорієнтовані на DynamicData. DynamicData Official Website.
  2. Офіційний вебсайт ReactiveUI. Для інформації про ReactiveUI, який тісно інтегрується з DynamicData, відвідайте офіційний вебсайт. Тут надається велика документація та уроки як для ReactiveUI, так і для DynamicData. ReactiveUI.
  3. Вступ до Rx — Реактивні розширення. ‘Вступ до Rx’ Лі Кемпбелла — це відмінний ресурс для розуміння Реактивних розширень (Rx), фундаментального концепту для роботи з DynamicData. Introduction to Rx.
  4. Офіційний репозиторій Rx.NET в GitHub від Microsoft. Оскільки DynamicData ґрунтується на Реактивних розширеннях (Rx), репозиторій Rx.NET на GitHub надає вичерпну інформацію про Rx, включаючи документацію API, зразки проєктів та внески спільноти. Це важливий ресурс для розробників, які прагнуть використовувати повну потужність реактивного програмування в .NET. Rx.NET on GitHub.
  5. DynamicData на GitHub. Основне джерело для вихідних кодів DynamicData, документації та останніх оновлень. Це корисний ресурс для розробників, які хочуть досліджувати можливості бібліотеки, вносити внески до її розвитку або звертатися за підтримкою у спільноту. Visit DynamicData on GitHub.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось4
До обраногоВ обраному3
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі