zoukankan      html  css  js  c++  java
  • Lind.DDD~实体属性变更追踪器的实现

    回到目录

    看着这个标题很复杂,大叔把它拆开说一下,实体属性-变更-追踪器,把它拆成三部分大家看起来就容易懂一些了,实体属性:领域实体里有自己的属性,属性有getter,setter块,用来返回和设置属性的内容;变更:当前属性为赋值时,我们对它进行监视;追踪器:对变量的内容进行处理。好了,我们回到Lind.DDD框架中,在框架里有领域实体基类EntityBase,这个类是所有实体的基类,它公开了一些属性和方法,我们对这个基类进行一些设置,让所有子类都继承它,享用它。

    1 属性变更追踪接口和它的事件

        // 摘要:
        //     向客户端发出某一属性值已更改的通知。
        public interface INotifyPropertyChanged
        {
            // 摘要:
            //     在更改属性值时发生。
            event PropertyChangedEventHandler PropertyChanged;
        }

    2 基类EntityBase,添加了事件和它的方法,及触发事件的方法

        /// <summary>
        /// 领域模型,实体模型基类,它可能有多种持久化方式,如DB,File,Redis,Mongodb,XML等
        /// Lind.DDD框架的领域模型与数据库实体合二为一
        /// </summary>
        [PropertyChangedAttribute]
        public abstract class EntityBase : ContextBoundObject, IEntity, INotifyPropertyChanged
        {
            /// <summary>
            /// 实体初始化
            /// </summary>
            public EntityBase()
            {
                this.Status = Status.Normal;
                this.UpdateDateTime = DateTime.Now;
                this.CreateDateTime = DateTime.Now;
                this.PropertyChanged += EntityBase_PropertyChanged;
            }
    
            /// <summary>
            /// 建立时间
            /// </summary>
            [XmlIgnore, DataMember(Order = 3), XmlElement(Order = 3), DisplayName("建立时间"), Column("CreateTime"), Required]
            public DateTime CreateDateTime { get; set; }
            /// <summary>
            /// 更新时间
            /// </summary>
            [XmlIgnore, DataMember(Order = 2), XmlElement(Order = 2), DisplayName("更新时间"), Column("UpdateTime"), Required]
            public DateTime UpdateDateTime { get; set; }
            /// <summary>
            /// 实体状态
            /// </summary>
            [XmlIgnore, DataMember(Order = 1), XmlElement(Order = 1), DisplayName("状态"), Required]
            public Status Status { get; set; }
    
            /// <summary>
            /// 拿到实体验证的结果列表
            /// 结果为null或者Enumerable.Count()==0表达验证成功
            /// </summary>
            /// <returns></returns>
            public IEnumerable<RuleViolation> GetRuleViolations()
            {
                var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray();
    
                foreach (var i in properties)
                {
                    var attr = i.GetCustomAttributes();
                    foreach (var a in attr)
                    {
                        var val = (a as ValidationAttribute);
                        if (val != null)
                            if (!val.IsValid(i.GetValue(this)))
                            {
                                yield return new RuleViolation(val.ErrorMessage, i.Name);
                            }
                    }
                }
    
            }
    
            #region PropertyChangedEventHandler Events
            /// <summary>
            /// 属性值变更事件
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;
            /// <summary>
            /// 事件实例
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void EntityBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                Console.WriteLine("属性:{0},值:{1}", e.PropertyName, sender.GetType().GetProperty(e.PropertyName).GetValue(sender));
            }
            /// <summary>
            /// 触发事件,写在每个属性的set块中CallerMemberName特性表示当前块的属性名
            /// </summary>
            /// <param name="propertyName"></param>
            public void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
            #endregion
    
        }

    3 定义变更拦截器特性

        /// <summary>
        /// 类中方法拦截的特性
        /// </summary>
        public class PropertyChangedAttribute : ProxyAttribute
        {
            public override MarshalByRefObject CreateInstance(Type serverType)
            {
                PropertyChangedProxy realProxy = new PropertyChangedProxy(serverType);
                return realProxy.GetTransparentProxy() as MarshalByRefObject;
            }
        }

    4 实现拦截器功能

        /// <summary>
        /// 属性变更拦截器
        /// </summary>
        public class PropertyChangedProxy : RealProxy
        {
            Type serverType;
            public PropertyChangedProxy(Type serverType)
                : base(serverType)
            {
                this.serverType = serverType;
            }
            public override IMessage Invoke(IMessage msg)
            {
                //构造方法
                if (msg is IConstructionCallMessage)
                {
                    IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage;
                    IConstructionReturnMessage constructionReturnMessage = this.InitializeServerObject((IConstructionCallMessage)msg);
                    RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue);
                    return constructionReturnMessage;
                }
                //其它方法(属性也是方法,它会被翻译成set_property,get_property,类似于java里的属性封装)
                else if (msg is IMethodCallMessage)
                {
    
                    IMethodCallMessage callMsg = msg as IMethodCallMessage;
                    object[] args = callMsg.Args;
                    IMessage message;
                    try
                    {
    
                        if (callMsg.MethodName.StartsWith("set_") && args.Length == 1)
                        {
                            string propertyName = Regex.Split(callMsg.MethodName, "set_")[1];
                            //这里检测到是set方法,然后应怎么调用对象的其它方法呢?
                            var method = this.serverType.GetMethod("OnPropertyChanged");
                            if (method != null)
                            {
                                var obj = GetUnwrappedServer();
                                obj.GetType().GetProperty(propertyName).SetValue(obj, args.FirstOrDefault());
                                method.Invoke(obj, new object[] { propertyName });//这块对象为空了
                            }
    
                        }
    
                        object o = callMsg.MethodBase.Invoke(GetUnwrappedServer(), args);
                        message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg);
                    }
    
                    catch (Exception e)
                    {
    
                        message = new ReturnMessage(e, callMsg);
    
                    }
    
                    return message;
    
                }
    
                return msg;
    
            }
        }

    5 总结

    本例子主要让大家了解了事件,事件触发机制,AOP拦截技术等知识点,而且通过本例子,我们可以对类的属性进行监视,并订阅一些方法来处理这些变更行为!下面这个代码是最简单的属性变更的记录,本user对象为赋值时,它的两个被set的属性成为了监视的对象

         User u1 = new User();
         u1.UserName = "OK";
         u1.Age = 100;

    回到目录

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 阮小二买彩票
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 企业奖金发放
    Java实现 蓝桥杯VIP 算法提高 企业奖金发放
    让程序后台隐藏运行
    只要你喜欢,并且可以养家糊口,就是好的
  • 原文地址:https://www.cnblogs.com/lori/p/5025964.html
Copyright © 2011-2022 走看看