总线模式

总线模式

为什么叫总线模式

当时我碰到的问题是这个样子的。我有一个叫做 BecomePaidMember(成为付费用户)的页面,这个页面涉及到的功能模块非常的多。然后我还有一个页面叫做UpgradePackage(升级包)的页面。里面同样包含了跟BecomePaidMember一样的东西,选择支付方式,选择合约时间,选择。。。有非常多的选择,未来也有可能加进新的选择。然后这些选择项之间又有互相关联,关系是不确定的(后面的需求会发生变化)。 比如选择了支付方式 1 就会造成选择合约的时间变化。合约时间的变化可能又会造成其它东西的变化。

这里面有一个东西是不太会变化的,就是哪些选择项还是有顺序的。就是有时候可能会触发一些事件有时候不会,总的发说是前面的会触发后面的。然后当时想到的是,计算机里面好象一个叫总线的东西然后数据都是通过它来传输的。然后我们的局域网(没有交换机)的情况下数据也是广播形式的传播然后每个网卡自己会去判断这个数据是不是发给它的。

为了结构的清晰很明显我们需要将每一个选择项做成 UserControl. 每一个需要刷新的显示单元也做成UserControl.

跟据一些旧的知识我们知道这边首先要彩用的是观察者模式(.net里可以用事件来),于是我们暴露了很多的事件

但是如果我们在页面来组织哪些事件的话,就会造成我们两个页面(未来可能三个或更多),我们就要写一大堆的事件处理的方法在页面哪边。并且如果是一个新的页面我们就要又多写一次了,所以我们使用新的方法来处理它,
我们可以在每一个项目里取一个叫做DataBus的类,然后再弄一个叫做UpgradeInfo的类。这个类里就放了很多的事件和属性,方法。用来协调哪些UserControl的。

    public class DataBus
    {
        private readonly static object upgradeKey = new object();
        public static UpgradeInfo UpgradeInfo
        {
            get
            {
                if (HttpContext.Current.Items.Contains(upgradeKey))
                {
                    return HttpContext.Current.Items[upgradeKey] as UpgradeInfo;
                }
                else
                {
                    UpgradeInfo info = new UpgradeInfo();
                    HttpContext.Current.Items.Add(upgradeKey, info);
                    return info;
                }
            }
        }
    }
UpgradeInfo的代码片断

public class UpgradeInfo

{

public int PackageID
        {
            get
            {
                if (ViewState["PackageID"] != null)
                {
                    return (int)ViewState["PackageID"];
                }
                return 0;
            }
            set
            {
                if (ViewState["PackageID"] != null)
                {
                    int temp = (int)ViewState["PackageID"];
                    if (temp != value)
                    {
                        ViewState["PackageID"] = value;
                        OnPackageChange();
                    }

                }
                else
                {
                    ViewState["PackageID"] = value;
                    OnPackageChange();
                }
            }

        }

#region event
        private EventHandlerList HandleList = new EventHandlerList();
        private static readonly object ActionPackage = new object();

 public event Action PackageChange
        {
            add
            {
                HandleList.AddHandler(ActionPackage, value);
            }
            remove
            {
                HandleList.RemoveHandler(ActionPackage, value);
            }
   /// <summary>
        /// When Select Package has been change
        /// </summary>
        private void OnPackageChange()
        {
            OnAction(ActionPackage);
        }
        public Func<int> CurrentStepFunc
        { get; set; }

}
有属性有事件有方法,然后某个UserControl自己注册事件,引发事件,如果可以提供Step信息的就自己去给CurrentStepFunc赋一个函数。

Ok大功告成。

真正的结构应该是另一种方式的,控件本身自己监听哪个数据(比如在Oninit的时候去判断某个东西有没有变化,但是实际情况可能不好这样做。因为usercontol加载还是有顺序的,结果某个东西可能就没的监听到所要的变化)
所以我们现在用的稍微有点点不一样的地方。

然后呢我们还会碰到一个问题。事件不断触发,绑定函数的重复调用

我们有一个FeeSummaryView的UserControl这个control在 pakcage变了 合约时间的变时候价格会发生变化。如果我们每次发生变化都要去直接调用,这个时候我们会想每次变化只调用一次就好了。(由于事件的传递会产生新的事件),后面我们参考了一下Usercontrol的生命周期,我们使用的一个变量IsDirty来标志这个控件是否需要更新,如果IsDirty是true的话则会被重新绑定了

private bool IsDirty
{
    get
    {
        if (ViewState["IsDirty"] != null)
        {
            return (bool)ViewState["IsDirty"];
        }
        return false;
    }
    set
    {
        ViewState["IsDirty"] = value;
    }

}
rotected override void OnPreRender(EventArgs e)
{
    Bind();
    base.OnPreRender(e);

}
private void Bind()
{
    if (IsDirty)
    {
        IsDirty=false;
    }
}
主要的思想还是把会变化的东西移到其它地方, 高内聚,低耦合
UserControl本身控件控制他自己所要控制的东西
原文地址:https://www.cnblogs.com/lovebanyi/p/1727015.html