nonepassby

导航

CSLA.NET快速入门系列——命令对象(CommandObject)

命令对象(CommandObject)是CSLA框架中另一类比较重要的对象,它主要用于在服务端执行一段代码,这段代码可能是简单的数据访问,也可能是复杂的工作流或其它可在服务端运行的对象。

 

命令对象的功能实际上也要以通过ReadOnlyBusiness对象来实现,但是使用ReadOnlyBusiness对象实现感觉复杂而不直观。而使用命令对象来实现则非常清晰而明确,即用于“运行服务器端命令“。

 

CSLA框架中提供了命令对象的基类:CommandBase<T>,该类提供了一个用来执行服务端代码的虚方法:

protected virtual void DataPortal_Execute()

在实现我们自己的命令对象时,需要继承CommandBase<T>基类,同时重写DataPortal_Execute方法实现真正的服务端代码。

 

如上面所说的,继承CommandBase<T>基类并重写DataPortal_Execute方法就已经实现了一个命令对象,不过,为了更加清晰和方便调用,CSLA命令对象一般会实现以下的编程模型:

提供一静态工厂方法(FactoryMethod)来供调用方使用本命令对象:

public static object Execute(object input,..)

该方法的输入参数可以为多个,提供实际的命令输入。

该方法的返回参数即为命令执行后的返回结果。

该方法的执行过程:

客户端代码(BeforeServer())=>服务端代码(DataPortal_Execute())=>客户端代码(AfterServer())

BeforeServer和AfterServer不是必须的,可以为空方法。

BeforeServer在服务端方法调用前做一些数据准备,同样AfterServer在服务端方法调用后做数据处理工作。

 

我们以CSLA中常用的ExsitsCommand举例命令对象的实现模式:

 

 [Serializable]
    [Csla.Server.ObjectFactory(FactoryNames.ExistsCommandFactoryName)]
    public class ExistsCommand : CommandBase<ExistsCommand>
    {
        #region Constructor(s)

        private ExistsCommand()
        {
        }


        #endregion

        #region Authorization Methods

        public static bool CanExecuteCommand()
        {
            return true;
        }

        #endregion

        #region Synchronous Factory Methods 

        public static bool Execute<T>(T criteria) where T : IGeneratedCriteria
        {
            if (!CanExecuteCommand())
                throw new System.Security.SecurityException("Not authorized to execute command");

            var cmd = new ExistsCommand();
            cmd.BeforeServer(criteria);
            cmd = DataPortal.Execute(cmd);
            cmd.AfterServer();

            return cmd.Result;
        }

        #endregion

        #region Client-side Code

        internal IGeneratedCriteria Criteria { getset; }
        public bool Result { getinternal set; }

        private void BeforeServer(IGeneratedCriteria criteria)
        {
            Criteria = criteria;
            Result = false;
        }

        private void AfterServer()
        {
        }

        #endregion
    }

 

在Client-side Code区域定义了:

  输入参数:internal IGeneratedCriteria Criteria { get; set; }

  输出参数:public bool Result { get; internal set; }

  BeforeServer方法:private void BeforeServer(IGeneratedCriteria criteria)

  AfterServer方法: private void AfterServer()

 

静态工厂方法实现则非常清晰简单:

public static bool Execute<T>(T criteria) where T : IGeneratedCriteria
        {
            if (!CanExecuteCommand())
                throw new System.Security.SecurityException("Not authorized to execute command");

            var cmd = new ExistsCommand();
            cmd.BeforeServer(criteria);
            cmd = DataPortal.Execute(cmd);
            cmd.AfterServer();

            return cmd.Result;
        }

 

本例由于采用FactoryObject模式,服务端方法没有直接在命令对象中实现,而是在相应的ObjectFactory类(由命令对象的ObjectFactoryAttribute中指定)中实现,代码发下:

 

#region Data Access


        public ExistsCommand Execute(ExistsCommand item)
        {
            string commandText = string.Format("SELECT COUNT(1) FROM {0} {1}", item.Criteria.TableFullName, ADOHelper.BuildWhereStatement(item.Criteria.StateBag));
            using (DbConnection connection = ADOHelper.CreateConnection())
            {
                connection.Open();
                using (DbCommand command = ADOHelper.CreateCommand(connection,commandText))
                {
                    command.Parameters.AddRange(ADOHelper.DbParameters(item.Criteria.StateBag));
                    item.Result = Convert.ToInt32(command.ExecuteScalar()) > 0;
                }
            }
            return item;
        }
        
        #endregion

 

通过上面的模式实现命令对象,调用方(UI或者其它对象)调用命令对象非常简单:

MyCriteria criteria;

// criteria = new MyCriteria();

bool result = ExistsCommand.Execute(criteria);

 

 

posted on 2012-08-01 15:53  jack  阅读(763)  评论(0)    收藏  举报