我打算明天贴一些自己目前正在用DCI架构编写的代码实例,望大家一起讨论和指教。

11-05-11 achilleswar
              

我打算明天贴一些自己目前正在用DCI架构编写的代码实例,届时希望大家能参与一起讨论,高人多多指教。

项目所属领域:基金领域

业务:申购基金、赎回基金、转换基金。

--------------------------------------------------------------------------------------

PPT:Fund(基金)

代码如下:

    /// <summary>
    /// 基金
    /// </summary>
    public class Fund : IAggregateRoot {

        /// <summary>
        /// 基金代码
        /// </summary>
        /// <param name="fundCode"></param>
        public Fund(string fundCode) {
             this.Code = fundCode;
        }

        /// <summary>
        /// 基金代码
        /// </summary>
        public string Code {
            get;
            set;
        }

        /// <summary>
        /// 基金名称
        /// </summary>
        public string Name {
            get;
            set;
        }

        /// <summary>
        /// 基金类型
        /// </summary>
        public FundType Type {
            get;
            set;
        }

        /// <summary>
        /// 基金种类(A类、B类、C类)
        /// </summary>
        public FundClass Class {
            get;
            set;
        }

        /// <summary>
        /// 基金所属公司
        /// </summary>
        public FundCompany Company {
            get;
            set;
        }

        /// <summary>
        /// 基金成立日期
        /// </summary>
        public DateTime SetupDate {
            get;
            set;
        }
    }
<p>

固有属性FundType(基金类型)

代码如下:

    /// <summary>
    /// 基金类型
    /// </summary>
    public class FundType : IValueObject {

        public FundType(int fundTypeCode, string fundTypeName) {
            this.Code = fundTypeCode;
            this.Name = fundTypeName;
        }

        /// <summary>
        /// 基金类型代码
        /// </summary>
        public int Code {
            get;
            set;
        }

        /// <summary>
        /// 基金类型名称
        /// </summary>
        public string Name {
            get;
            set;
        }
    }
<p>

固有属性FundClass(基金种类)

代码如下:

    /// <summary>
    /// 基金种类
    /// </summary>
    public enum FundClass {
        /// <summary>
        /// A类基金
        /// </summary>
        A = 1,
        /// <summary>
        /// B类基金
        /// </summary>
        B = 2,
        /// <summary>
        /// C类基金
        /// </summary>
        C = 3
    }
<p>

固有属性FundCompany(基金所属公司)

代码如下:

    /// <summary>
    /// 基金所属公司
    /// </summary>
    public class FundCompany : IValueObject {

        public FundCompany(string fundCompanyId, string fundCompanyName) {
            this.Id = fundCompanyId;
            this.Name = fundCompanyName;
        }

        /// <summary>
        /// 基金所属公司编号/代码
        /// </summary>
        public string Id {
            get;
            set;
        }

        /// <summary>
        /// 基金所属公司编号名称
        /// </summary>
        public string Name {
            get;
            set;
        }
    }
<p>

[该贴被achilleswar于2011-05-12 08:38修改过]

              

1
achilleswar
2011-05-12 08:48

好了,基金要参与申购业务了。

首先请出SubscribeFund("申购的基金"角色)

代码如下:

    /// <summary>
    /// 申购的基金
    /// </summary>
    public class SubscribeFund : IRole {

        private Fund _fund;

        public SubscribeFund(Fund fund) {
            this._fund = fund;
        }

        public string Code {
            get {
                return this._fund.Code;
            }
        }

        /// <summary>
        /// 基金不存在
        /// </summary>
        public bool NotExists {
            get {
                return this._fund == null;
            }
        }

        /// <summary>
        /// 封闭式、创新型封闭式、理财产品、QDII和首发基金不允许购买
        /// </summary>
        public bool CannotBuy {
            get {
                bool isCannotBuyFundType = false;
                switch (this._fund.Type.Code) {
                    case 6:
                        isCannotBuyFundType = true;
                        break;
                    case 7:
                        isCannotBuyFundType = true;
                        break;
                    case 9:
                        isCannotBuyFundType = true;
                        break;
                    case 10:
                        isCannotBuyFundType = true;
                        break;
                }
                bool isUnSetuppedFund = (this._fund.SetupDate == DateTime.MinValue);
                return isCannotBuyFundType || isUnSetuppedFund;
            }
        }

        /// <summary>
        /// 基金是否处于封闭期或暂停申购
        /// </summary>
        public bool SubscribeClosed {
            get {
                string fundCode = this._fund.Code;
                return FundService.IsSubscribeClosed(fundCode);
            }
        }
    }
<p>

再请出SubscribeUser ("申购的用户"角色)

代码如下:

    /// <summary>
    /// 申购的用户
    /// </summary>
    public class SubscribeUser : IRole {

        private User _user;

        public SubscribeUser() {

        }

        public SubscribeUser(User user) {
            this._user = user;
        }

        /// <summary>
        /// 用户不存在
        /// </summary>
        public bool NotExists {
            get {
                return this._user == null;
            }
        }

        /// <summary>
        /// 用户被禁赛
        /// </summary>
        public bool Suspended {
            get {
                return this._user.IsActive == false;
            }
        }

        /// <summary>
        /// 选手允许购买的基金
        /// </summary>
        public IList<SubscribeFund> CanBuyFunds {
            get {
                return new List<SubscribeFund>();
            }
        }

        /// <summary>
        /// 用户是否不允许购买基金
        /// </summary>
        /// <param name="fund"></param>
        /// <returns></returns>
        public bool CannotBuyFund(SubscribeFund fund) {
            return !(this.CanBuyFunds.Count == 0 || this.CanBuyFunds.Contains(fund));
        }

        /// <summary>
        /// 用户账户余额不足
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool InsufficientBalance(decimal amount) {
            return this._user.Account.Balance < amount;
        }
    }
<p>

接着SubscribeContext("基金申购"场景)粉墨登场

代码如下:

    /// <summary>
    /// 基金申购场景
    /// </summary>
    public class SubscribeContext : IContext {

        private SubscribeUser _user;
        private SubscribeFund _fund;
        private decimal _amount;

        public SubscribeContext(
            SubscribeUser user
            ,SubscribeFund fund
            , decimal amount
        ) {
            this._user = user;
            this._fund = fund;
            this._amount = amount;
        }

        public ActionResponse Interact() {
            ActionResponse response = new ActionResponse();
            //验证基金是否存在
            if (this._fund.NotExists) {
                return new FailureResponse(
                    MessageResourceManager.GetMessage("ERR_NOT_EXISTS_FUND").Code
                    , MessageResourceManager.GetMessage("ERR_NOT_EXISTS_FUND").Text
                );
            }
            //封闭式、创新型封闭式、理财产品、QDII和首发基金不允许购买
            if (this._fund.CannotBuy) {
                return new FailureResponse(
                    MessageResourceManager.GetMessage("ERR_CAN_NOT_BUY_FUND").Code
                    , MessageResourceManager.GetMessage("ERR_CAN_NOT_BUY_FUND").Text
                );
            }
            //验证基金是否处于封闭期或暂停申购
            if (this._fund.SubscribeClosed) {
                return new FailureResponse(
                    MessageResourceManager.GetMessage("ERR_SUBSCRIBE_CLOSED_FUND").Code
                    , MessageResourceManager.GetMessage("ERR_SUBSCRIBE_CLOSED_FUND").Text
                );
            }
            //验证用户是否允许购买此基金
            if (this._user.CannotBuyFund(this._fund)) {
                return new FailureResponse(
                    MessageResourceManager.GetMessage("ERR_CAN_NOT_BUY_THIS_FUND_USER").Code
                    , MessageResourceManager.GetMessage("ERR_CAN_NOT_BUY_THIS_FUND_USER").Text
                );
            }
            //验证用户帐户余额是否不足
            if (this._user.InsufficientBalance(this._amount)) {
                return new FailureResponse(
                    MessageResourceManager.GetMessage("ERR_INSUFFICIENT_BALANCE").Code
                    , MessageResourceManager.GetMessage("ERR_INSUFFICIENT_BALANCE").Text
                );
            }
            //验证交易金额
            SubscribeAmountValidationContext subscribeAmountValidationContext = new SubscribeAmountValidationContext(this._amount);
            SubscribeAmountValidator subscribeAmountValidator = ValidatorFactory.CreateSubscribeAmountValidator(subscribeAmountValidationContext);
            ValidationResult amountValidationResult = subscribeAmountValidator.Validate();
            if (amountValidationResult.InValid) {
                return new FailureResponse(
                    amountValidationResult.StatusCode
                    , amountValidationResult.StatusText
                );
            }
            //验证资产配置
            AssetValidationContext assetValidationContext = new AssetValidationContext(
                new SubscribeUser()
                , this._fund
                , this._amount
            );
            AssetValidator assetValidator = ValidatorFactory.CreateAssetValidator(assetValidationContext);
            ValidationResult assetValidationResult = assetValidator.Validate();
            if (assetValidationResult.InValid) {
                return new FailureResponse(
                    assetValidationResult.StatusCode
                    , assetValidationResult.StatusText
                );
            }
            return response;
        }
    }
<p>

[该贴被achilleswar于2011-05-12 08:52修改过]

achilleswar
2011-05-12 08:56

domain service层构建一个互动的环境

/// <summary>
    /// 基金申购服务
    /// </summary>
    public class SubscribeService {

        /// <summary>
        /// 申购基金
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="fundCode"></param>
        /// <param name="amount"></param>
        /// <param name="remark"></param>
        /// <returns></returns>
        public virtual ActionResponse Subscribe(
            int userId
            , string fundCode
            , decimal amount
            , string remark
        ) {
            ActionResponse response = new ActionResponse();
            IUserRepository userRepository = RepositoryFactory.CreateUserRepository();
            User user = userRepository.GetUser(userId);
            Fund fund = FundFactory.BuildFund(fundCode);
            IContext context = new SubscribeContext(
                new SubscribeUser(user)
                , new SubscribeFund(fund)
                , amount
            );
            response = context.Interact();
            return response;
        }
    }
<p>

这里部分代码先略,如ActionResponse,这是一个响应

achilleswar
2011-05-12 09:00

忘了贴上PPT用户了,在此补上

PPT:User(用户)

代码如下:

    /// <summary>
    /// 用户
    /// </summary>
    public class User {

        /// <summary>
        /// 用户编号
        /// </summary>
        public int Id {
            get;
            set;
        }

        /// <summary>
        /// 用户名称
        /// </summary>
        public string Name {
            get;
            set;
        }

        /// <summary>
        /// 用户帐户
        /// </summary>
        public Account Account {
            get;
            set;
        }

        /// <summary>
        /// 用户所属组
        /// </summary>
        public Team Team {
            get;
            set;
        }

        /// <summary>
        /// 用户状态
        /// </summary>
        public bool IsActive {
            get;
            set;
        }

        /// <summary>
        /// 注册日期
        /// </summary>
        public DateTime RegisterDate {
            get;
            set;
        }
    }
<p>

用户的固有属性Account(账户)

代码如下

    /// <summary>
    /// 用户帐户
    /// </summary>
    public class Account : IValueObject {

        /// <summary>
        /// 用户总资产
        /// </summary>
        public decimal TotalAsset {
            get;
            set;
        }

        /// <summary>
        /// 账户余额
        /// </summary>
        public decimal Balance {
            get;
            set;
        }
    }
<p>

用户的固有属性Team(组)

代码如下:

    /// <summary>
    /// 组
    /// </summary>
    public class Team : IValueObject {

        /// <summary>
        /// 小组代码
        /// </summary>
        public int Code {
            get;
            set;
        }

        /// <summary>
        /// 小组名称
        /// </summary>
        public string Name {
            get;
            set;
        }

        /// <summary>
        /// 本组初始本金
        /// </summary>
        public decimal Principal {
            get;
            set;
        }
    }
<p>

[该贴被achilleswar于2011-05-12 09:20修改过]

banq
2011-05-12 16:28

不错,其实你的申购用户subscribeuser 已经是一个角色,可能你没有发觉。

3Go 1 2 3 下一页