前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c#开发的ref和watch实现--轻松完成响应式开发--

c#开发的ref和watch实现--轻松完成响应式开发--

原创
作者头像
是谁抢了www名字
发布2024-08-22 22:49:58
990
发布2024-08-22 22:49:58
代码语言:txt
复制
using System;
using System.Collections.Generic;


public class Observable
{
    private readonly Dictionary<string, List<Action<object, object>>> _propertyObservers = new();

    public ObservableProperty<T> Ref<T>(T initialValue, string propertyName)
    {
        return new ObservableProperty<T>(initialValue, this, propertyName);
    }

    public ObservableList<T> RefList<T>(IList<T> initialValue, string propertyName)
    {
        var list = new ObservableList<T>(initialValue, this, propertyName);
        return list;
    }

    public void Watch(string propertyName, Action<object, object> callback)
    {
        if (!_propertyObservers.ContainsKey(propertyName))
        {
            _propertyObservers[propertyName] = new List<Action<object, object>>();
        }

        _propertyObservers[propertyName].Add(callback);
    }

    public void Unwatch(string propertyName, Action<object, object> callback)
    {
        if (_propertyObservers.ContainsKey(propertyName))
        {
            _propertyObservers[propertyName].Remove(callback);
        }
    }

    public void NotifyPropertyChange(string propertyName, object oldValue, object newValue)
    {
        if (_propertyObservers.TryGetValue(propertyName, out var callbacks))
        {
            foreach (var callback in callbacks)
            {
                callback?.Invoke(oldValue, newValue);
            }
        }
    }
}
复制
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

public class ObservableProperty<T>
{
    private T _value;
    private readonly Observable _observable;
    private readonly string _propertyName;

    public ObservableProperty(T initialValue, Observable observable, string propertyName)
    {
        _value = initialValue;
        _observable = observable;
        _propertyName = propertyName;
    }

    public string PropertyName => _propertyName;

    public T Value
    {
        get => _value;
        set
        {
            if (!EqualityComparer<T>.Default.Equals(_value, value))
            {
                T oldValue = _value;
                _value = value;
                _observable.NotifyPropertyChange(_propertyName, oldValue, value);
            }
        }
    }
}
public class ObservableList<T> : Collection<T>
{
    private readonly Observable _observable;
    private readonly string _propertyName;

    public ObservableList(IList<T> list, Observable observable, string propertyName)
        : base(list)
    {
        _observable = observable;
        _propertyName = propertyName;
    }

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        NotifyChange();
    }

    protected override void SetItem(int index, T item)
    {
        T oldItem = Items[index];
        base.SetItem(index, item);
        NotifyChange(oldItem, item);
    }

    protected override void RemoveItem(int index)
    {
        T item = Items[index];
        base.RemoveItem(index);
        NotifyChange(item, default(T)); // 使用 default(T) 来代表 null
    }

    protected override void ClearItems()
    {
        var oldItems = Items.ToList(); // 将 Items 转换为 List<T>
        base.ClearItems();
        NotifyChange(oldItems, new List<T>());
    }

    private void NotifyChange(T oldValue, T newValue)
    {
        _observable.NotifyPropertyChange(_propertyName, oldValue, newValue);
    }

    private void NotifyChange()
    {
        _observable.NotifyPropertyChange(_propertyName, null, null);
    }

    private void NotifyChange(List<T> oldValues, List<T> newValues)
    {
        _observable.NotifyPropertyChange(_propertyName, oldValues, newValues);
    }
}

使用方法:

代码语言:txt
复制
public Observable _observable = new Observable();

对于只是监听对象的变化而不去关注某一项的变化的话可以使用如下方式:

代码语言:txt
复制
    public ObservableProperty<string> Time { get; set; }
       public PlayerCompany()

    {

        Time = _observable.Ref("Initial Time", nameof(Time));

    }

我这段使用的是单例模式,所以用了一个构造函数,这样方便管理与维护

如果力邀使用较为特殊的情况,需要监听每一项值得变化得话你可以使用如下方式:

代码语言:txt
复制
    public ObservableList<Employee> Mangers { get; set; }
    public PlayerCompany()

    {

        Mangers = _observable.RefList(new List<Employee> { null},nameof(Mangers));

    }

上面得方式是注册一个被观察对象放在观察列表中,那么下面将告诉你如何使用watch了。

代码语言:txt
复制
 PlayerCompany.Instance._observable.Watch(nameof(PlayerCompany.Time), _timeChangeCallback = (oldValue, newValue) =>
 {

 });

这个watch提供了两个参数,第一个就是注册被观察对象得键值,第二个是一个回调函数,这个回调函数给定一个改版之前得值和改变之后的值。

如果是要关注每一项值的变化注册的被观察对象那么虽然使用的都是watch但是oldValue和newValue给的值并不是所有的值都给,而是哪一个值发生了改变哪一个值就会被单独拎出来通过oldValue和newValue返回新旧的值。

当然,考虑到性能问题,所以提供了Unwatch函数,就是用来随时关闭侦听的,性能问题就会根据使用场景而变化了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档