C# “如何结合”;IObservable<;布尔>;IsActive";及;“bool IsEnabled”;一分为二

C# “如何结合”;IObservable<;布尔>;IsActive";及;“bool IsEnabled”;一分为二,c#,reactive-programming,system.reactive,rx.net,C#,Reactive Programming,System.reactive,Rx.net,有两个属性,一个是public-IObservable-isnabled{get;set;}类型,另一个是public-bool-IsActive{get;set;}类型,我想使用System.Reactive将这两个属性组合在一个属性中,就像public-bool-IsActiveAndEnabled{get;set;} public class BindableProperty<T> { T Value { get; } } public class Manager

有两个属性,一个是
public-IObservable-isnabled{get;set;}
类型,另一个是
public-bool-IsActive{get;set;}
类型,我想使用
System.Reactive
将这两个属性组合在一个属性中,就像
public-bool-IsActiveAndEnabled{get;set;}

public class BindableProperty<T> 
{
    T Value { get; }
}

public class Manager
{
    public IObservable<bool> IsEnabled { get; set; }

    public BindableProperty<bool> IsActiveAndEnabled { get; set; }


    private bool isActive;
    public bool IsActive
    {
        get { return isActive; }
        set
        {
            isActive = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged(() => IsActive);
        }
    }

    private void OnPropertyChanged(Func<bool> property)
    {
        throw new NotImplementedException();
    }

    public Manager()
    {
        IsEnabled
            .And(/* accept only observable, but I want to join with IsActive*/)
            .Then((isEnabled,isActive) => IsActiveAndEnabled = isEnabled && isActive);
    }
}
公共类BindableProperty
{
T值{get;}
}
公共班级经理
{
公共IObservable IsEnabled{get;set;}
public BindableProperty IsActiveAndEnabled{get;set;}
私人住宅是活跃的;
公共福利活动
{
获取{return isActive;}
设置
{
i活跃=价值;
//每当更新属性时调用OnPropertyChanged
OnPropertyChanged(()=>IsActive);
}
}
私有void OnPropertyChanged(Func属性)
{
抛出新的NotImplementedException();
}
公共经理()
{
我迷路了
.和(/*只接受可观察,但我想加入IsActive*/)
。然后((isEnabled,isActive)=>IsActivateAndEnabled=isEnabled&&isActive);
}
}
  • 您发布的代码不是如何使用反应式编程范例的好例子

    • 请不要将“可观察”视为类a可变对象的单个标量值成员属性的视图。
      • 我责怪微软让人们产生这种误解,因为多年前他们在.NET框架中添加了
        observateCollection
        ,但他们(错误地)在
        observateCollection
        上下文中使用了“observate”一词,这与反应式编程中的
        observateCollection
        的含义完全无关
  • 在执行反应式编程时,可观察对象是数据对象流的源(或发射器)(请注意,流可以是空的(从不发射任何东西),或者在关闭自身之前只发射单个对象,或者每秒发射数千个对象)

  • 因此,
    IObservable
    最好被认为是一个“
    IEnumerable
    ”,它推动(与具有“pull”语义的正常
    IEnumerable
    相比)
  • 另一件重要的事情是,可观测对象发出的对象应该(不,必须)是不可变的或者至少,发出的对象不能与任何其他发出的对象共享可变状态!
    • 这是因为如果一个值随着时间的推移而改变,或者如果对一个对象的更改会影响其他对象,那么程序中使用返回对象的不同实例的其他部分的状态将发生变化,而不会发生预期的变化
在继续下一步之前,我强烈建议您遵循关于反应式编程概念的指南或教程。大多数指南和教程都涉及RxJS(JavaScript的反应式扩展,在Angular决定为其内置HTTP客户端库使用
Observable
而不是
Promise
后,这一功能得到了普及。虽然许多指南都涉及RxJS,但它们完全适用于其他平台(如.NET)的反应式编程(虽然
IObservable
是.NET Framework的一部分,但您需要单独的反应式扩展库来正确地进行反应式编程,而无需重新发明轮子)

重要提示:(存在切向关系,但它们是完全独立的事物)

资源:

  • 导言:
  • .NET的反应式扩展:
关于你的情况,我的建议如下:

如果类管理器
必须是可变的:
  • Remove
    public IObservable IsEnabled{get;set;}
  • 定义一个新的不可变的
    类管理器状态
  • 扩展
    类管理器:IObservable
  • 每当
    类管理器
    中的可变属性发生更改时,向订阅服务器发送一个新的
    管理器状态
    (使用
    管理器
    的快照副本填充)
如果
类管理器
可以设置为不可变:
  • Remove
    public IObservable IsEnabled{get;set;}
  • 定义一个新类
    ManagerSource
    ,它实现了
    IObservable
  • 每次以某种方式更新
    管理器
    时,向订阅服务器发送一个新的
    管理器
    对象(用
    管理器
    的快照副本填充)
示例(当
类管理器
是可变的时):
听起来这是一个很有价值的目标。你被困在哪里了?你能给我们看看你的实际代码而不是一堆属性签名吗?你被困在哪里了?嗨@Enigmativity,我提供了更多的信息,希望我说得很清楚。你确定要在
IObservable
中放一个标量值而不是主题类型吗?不清楚是什么
BindableProperty
是或如何更新它,因此我将假定一个普通属性的形式为
public bool IsActiveAndEnabled{get;private set;}
。在这种情况下,
IsEnabled.StartWith(true).Subscribe(IsEnabled=>IsActiveAndEnabled=IsEnabled&&IsActivity)
为您工作?是的,我认为微软引入IAsyncEnumerable会让事情变得更加混乱,在我看来,IAsyncEnumerable试图实现与可观测流相同的目的,但具有异步延续性。@Frank imho
IAsyncEnumerable
非常容易理解。@Asti我觉得虽然IAsyncEnumerable是可以理解的,但它是c我同意的一点是,先生,你是一位学者,也是一位绅士。我唯一的遗憾是,我只能投一票
class Manager : IObservable<ManagerState>
{
    private Boolean isEnabled; // backing field
    public Boolean IsEnabled
    {
        get { return this.isEnabled; }
        set
        {
            this.isEnabled = value;
            this.NotifySubscribers();
        }
    }

    private Boolean isActive; // backing field
    public Boolean IsActive
    {
        get { return this.isActive; }
        set
        {
            this.isActive = value;
            this.NotifySubscribers();
        }
    }

    #region Observers (Subscribers) handling:

    private readonly ConcurrentBag<IObserver<ManagerState>> subscribers = new ConcurrentBag<IObserver<ManagerState>>();

    private void NotifySubscribers()
    {
        ManagerState snapshot = new ManagerState(
            this.IsEnabled,
            this.IsActive,
            // etc
        );

        foreach( IObserver<ManagerState> observer in this.subscribers )
        {
            observer.OnNext( snapshot );
        } 
    }

    #endregion
}

// Represents a snapshot of the state of a `Manager`
class ManagerState
{
    public ManagerState( Boolean isEnabled, Boolean isActive )
    {
        this.IsEnabled = isEnabled;
        this.IsActive  = isActive;
    }

    public Boolean IsEnabled { get; }
    public Boolean IsActive  { get; }
    // any other members, etc
}
class Manager : IObservable<ManagerState>, INotifyPropertyChanged
{
    private Boolean isEnabled; // backing field
    public Boolean IsEnabled
    {
        get { return this.isEnabled; }
        set
        {
            this.isEnabled = value;
            this.OnPropertyChanged( nameof(this.IsEnabled) );
        }
    }

    private Boolean isActive; // backing field
    public Boolean IsActive
    {
        get { return this.isActive; }
        set
        {
            this.isActive = value;
            this.OnPropertyChanged( nameof(this.IsActive) );
        }
    }

    #region INotifyPropetyChanged and Observers (Subscribers) handling:

    private readonly ConcurrentBag<IObserver<ManagerState>> subscribers = new ConcurrentBag<IObserver<ManagerState>>();

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged( String name )
    {
        // First, notify users of INotifyPropetyChanged:

        this.PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( name ) );

        // Then notify users of IObservable:

        ManagerState snapshot = new ManagerState(
            this.IsEnabled,
            this.IsActive,
            // etc
        );

        foreach( IObserver<ManagerState> observer in this.subscribers )
        {
            observer.OnNext( snapshot );
        } 
    }

    #endregion
}