采用了Restful WebApi的架構(gòu),再把業(yè)務(wù)邏輯狀態(tài)轉(zhuǎn)移放到后端就有點違背初衷了。實際上只要后端Api的權(quán)限設(shè)置的好,把狀態(tài)轉(zhuǎn)移放到前端也未嘗不可。我考慮的結(jié)果是,一般如果變更這個狀態(tài)本身就需要特定權(quán)限才可操作,比如xxx審批者,在前端處理狀態(tài)邏輯問題不大,因為本身這個人就是有權(quán)限的,如果偽造請求破壞了數(shù)據(jù)也可以通過Log定位到個人,但是如果是面向大眾的情況,比如團(tuán)購下個訂單什么的不對數(shù)據(jù)有特定權(quán)限要求的就需要在后端單獨做動作類的WebApi了,歡迎討論。
相關(guān)傳送門:Restful WebApi開發(fā)實踐
先來看下最后的請求效果:(插件服務(wù)總線用的是服務(wù)定位器設(shè)計模式)
var result = BundleServiceBus.Current.GetInstance<IEventHandleService>() .EventTrigger<ExamEvent>(new ExamEvent {     RootDataId = Id,     Type = ET, });if (result.IsSuccess){    Dispatcher.Invoke(() => MessageBox.Show("提交成功"));    UpdateStudentInfo(ThisStudentInfo.Id);    return;}這里我們將用到 C#對WebApi數(shù)據(jù)操作 里的方案來解決數(shù)據(jù)操作環(huán)節(jié)。
首先定義狀態(tài)基類:
abstract class StatusBase<RootDataType>{    public ReturnHTTPData ReturnHttpData { get; set; }    public abstract string Name { get; }    public virtual bool Entry(BaseEvent arg) { return true; }    public virtual bool Exit() { return true; }    public abstract List<BaseTransferModel> TransferList { get; }    public IModelDataService MDS = BundleServiceBus.Current.GetInstance<IModelDataService>();    public RootDataType RootData { get; set; }}這里需要根據(jù)具體數(shù)據(jù)類型自定義一個業(yè)務(wù)狀態(tài)基類,比如:
abstract class XXXStatusBase : StatusBase<StudentInfoModel>{    public LoginUserInfoModel CurrentLoginUser    {        get        {            return MDS.GetDataByModel<LoginUserInfoModel, string>(DataParameter.Empty).Data.SingleOrDefault();        }    }    public bool ChangeRootDataStatus(string TargetStatus)    {        RootData.Status = TargetStatus;        return ChangeRootDataInfo(RootData);    }    public bool ChangeRootDataInfo(StudentInfoModel model)    {        var result = MDS.PutDataByModel(new DataParameter<Guid>        {            TenantId = CurrentLoginUser.GetDataParameter().TenantId,            AggregationId = CurrentLoginUser.GetDataParameter().AggregationId,            SiteId = CurrentLoginUser.GetDataParameter().SiteId,            DataId = model.Id,            CMD = CurrentLoginUser.GetDataParameter().CMD        }, model);        //ReturnHttpData = new ReturnHTTPData { Content = result.Message };        return result.IsSuccess;    }    public bool AddBusinessLog(BusinessLogModel model)    {        //TODO 提交隊列        var result = MDS.PostDataByModel<BusinessLogModel, Guid>(CurrentLoginUser.GetDataParameter(), model);        //ReturnHttpData = new ReturnHTTPData { Content = result.Message };        return result.IsSuccess;    }}接下來定義一下狀態(tài)轉(zhuǎn)移模型基類:
abstract class BaseTransferModel{    public string Target { get; set; }    public abstract bool Condition(BaseEvent arg);    public abstract bool Action(string target, BaseEvent arg);}實現(xiàn)一個基于事件的狀態(tài)轉(zhuǎn)移模型:
class TransferModel<TEvent> : BaseTransferModel    where TEvent : BaseEvent{    public override bool Condition(BaseEvent arg)    {        var carg = arg as TEvent;        return carg != null && ConditionFunc(carg);    }    public override bool Action(string target, BaseEvent arg)    {        var carg = arg as TEvent;        return carg != null && ActionFunc(target, carg);    }    public Func<TEvent, bool> ConditionFunc { PRivate get; set; }    public Func<string, TEvent, bool> ActionFunc { private get; set; }}剩下的就是狀態(tài)機(jī)主體了,通過反射添加狀態(tài),并檢查狀態(tài)轉(zhuǎn)移關(guān)系:
class StatusManager{    public List<string> LostStatus { get; set; }    private Dictionary<string, XXXStatusBase> StatusData = new Dictionary<string, XXXStatusBase>();    private IModelDataService MDS = BundleServiceBus.Current.GetInstance<IModelDataService>();    LoginUserInfoModel CurrentLoginUser    {        get        {            return MDS.GetDataByModel<LoginUserInfoModel, string>(DataParameter.Empty).Data.SingleOrDefault();        }    }    public StatusManager()    {        LostStatus = new List<string>();        var data = Assembly.GetExecutingAssembly().DefinedTypes.Where(s => s.BaseType == typeof(XXXStatusBase));        foreach (var typeInfo in data)        {            var status = Activator.CreateInstance(typeInfo) as XXXStatusBase;            try            {                StatusData.Add(status.Name, status);            }            catch (Exception)            {                LostStatus.Add("AddError " + status.Name);            }        }        //自檢        foreach (var st in StatusData.Values)        {            foreach (var tr in st.TransferList)            {                if (StatusData.All(s => s.Key != tr.Target))                {                    LostStatus.Add(st.Name + " [To] " + tr.Target);                }            }        }        if (LostStatus.Count > 0)        {            Debug.WriteLine("Status has Errors!");        }    }    public List<Type> GetCurrentCanUseEvent(string Status)    {        var data = new List<Type>();        if (StatusData.Keys.All(s => s != Status)) return data;        foreach (var transfer in StatusData[Status].TransferList)        {            data.AddRange(transfer.GetType().GenericTypeArguments);        }        return data;    }    public EventResult Trigger(BaseEvent arg)    {        //準(zhǔn)備狀態(tài)轉(zhuǎn)移主體        var RootData = new StudentInfoModel { Status = "" };        if (arg.RootDataId != Guid.Empty)        {            var data = MDS.GetDataByModel<StudentInfoModel, Guid>(new DataParameter<Guid>            {                TenantId = CurrentLoginUser.GetDataParameter().TenantId,                SiteId = CurrentLoginUser.GetDataParameter().SiteId,                DataId = arg.RootDataId,            });            if (!data.IsSuccess)            {                return new EventResult                {                    IsSuccess = false,                    Result = data.Message                };            }            RootData = data.Data.SingleOrDefault();        }        //狀態(tài)轉(zhuǎn)移引擎        if (StatusData.Keys.All(s => s != RootData.Status)) return new EventResult        {            IsSuccess = false,            Result = "狀態(tài)[" + RootData.Status + "]不存在"        };        var status = StatusData[RootData.Status];        if (status == null)        {            return new EventResult            {                IsSuccess = false,                Result = "NotFoundStatus"            };        }        status.RootData = RootData;        foreach (var transfer in status.TransferList)        {            if (!transfer.Condition(arg)) continue;            status.Exit();            if (!transfer.Action(transfer.Target, arg))            {                if (status.ReturnHttpData == null)                {                    status.ReturnHttpData = new ReturnHTTPData();                }                return new EventResult                {                    IsSuccess = false,                    Result = status.ReturnHttpData.Content,                };            }            if (StatusData.Keys.All(s => s != RootData.Status))            {                if (status.ReturnHttpData == null)                {                    status.ReturnHttpData = new ReturnHTTPData();                }                return new EventResult                {                    IsSuccess = true,                    Result = status.ReturnHttpData.Content,                };            }            if (StatusData[transfer.Target].Entry(arg))            {                if (status.ReturnHttpData == null)                {                    status.ReturnHttpData = new ReturnHTTPData();                }                return new EventResult                {                    IsSuccess = true,                    Result = status.ReturnHttpData.Content,                };            }            if (status.ReturnHttpData == null)            {                status.ReturnHttpData = new ReturnHTTPData();            }            return new EventResult            {
新聞熱點
疑難解答