Catel帮助手册-Catel.Core:(4)数据处理

1,概要

 

   文档的这个部分都是关于Catel中数据处理方法的,一些部分是基于CodeProject上的文章的,但这个文档有更多的更新内容。

    一件很重要的事情是许多开发者花费很多时间来处理对象的序列化,序列化是一个专业领域的知识,只有技术比较高深的人员才能很好地掌握对象的序列化处理(要考虑程序集的改变,类的改变(属性的增加和移除),大部分开发者认为序列化只是执行如下的操作代码创建一个BinaryFormattter对象:

var serializer = new BinaryFormatter();
var myObject = (MyObject)serializer.Deserialize(stream);

大部分的开发者并不知道在如下情况下,序列化会出现问题

1,你更改了你的程序集版本

2,你增加或减少了一个属性字段

3,你增加或减少了一个事件

  甚至如果你知道,它也需要很多的知识点来解决这个问题,我也是在我足够能够把握这个知识点后才来编写序列化的方法,这个方法是ModelBase类,这个能作为数据对象的基类使用,可以存储到内存也可以序列化到磁盘(或者stream,或者XML,等等…)

2,ObservableObject对象

ObservableObject对象是一个非常轻量级的类仅仅实现了INotifyPropertyChanging和INotifyPropertyChanged接口,这个类是简单对象,仅仅需要属性通知,下面是一个例子:

 

 

public class Person : ObservableObject
{
    private string _firstName;
    private string _middleName;
    private string _lastName;

    public Person(string firstName, string middleName, string lastName)
    {
        FirstName = firstName;
        MiddleName = middleName;
        LastName = lastName;
    }

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            RaisePropertyChanging(() => FirstName);

            var oldValue = _firstName;
            _firstName = value;
            RaisePropertyChanged(() => FirstName, oldValue, value);
        }
    }

    public string MiddleName
    {
        get { return _middleName; }
        set
        {
            RaisePropertyChanging(() => MiddleName);
            var oldValue = _middleName;
            _middleName = value;
            RaisePropertyChanged(() => MiddleName, oldValue, value);
        }
    }

    public string LastName
    {
        get { return _lastName; }
        set
        {
            RaisePropertyChanging(() => LastName);
            var oldValue = _lastName;
            _lastName = value;
            RaisePropertyChanged(() => LastName, oldValue, value);
        }
    }
}

3,DispacherObservableObject

DispatchObservableObject是一个类,继承于ObjservableObject类,这个类的唯一不同是,这个对象会将所有的属性更改反应到UI线程上,下面是一个使用DispatcherObservableObject对象的方法,这是一个线程安全的更改观察.

public class Person : DispatcherObservableObject
{
    private string _firstName;
    private string _middleName;
    private string _lastName;

    public Person(string firstName, string middleName, string lastName)
    {
        FirstName = firstName;
        MiddleName = middleName;
        LastName = lastName;
    }

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            RaisePropertyChanging(() => FirstName);

            var oldValue = _firstName;
            _firstName = value;
            RaisePropertyChanged(() => FirstName, oldValue, value);
        }
    }

    public string MiddleName
    {
        get { return _middleName; }
        set
        {
            RaisePropertyChanging(() => MiddleName);
            var oldValue = _middleName;
            _middleName = value;
            RaisePropertyChanged(() => MiddleName, oldValue, value);
        }
    }

    public string LastName
    {
        get { return _lastName; }
        set
        {
            RaisePropertyChanging(() => LastName);
            var oldValue = _lastName;
            _lastName = value;
            RaisePropertyChanged(() => LastName, oldValue, value);
        }
    }
}

 

4,ModelBase

ModelBase(以前是DataObjectBase)类,是一个泛型基类,能够被使用到你所有的数据类上.

序列化

可以将对象存储到硬盘或者序列化到内存,或者二进制文件或者XML,数据对象,数据对象支持立即可用,以及动态处理序列化和反序列化。

支持属性变化观察

这个类支持INotifyPropertyChanging和INotifyChanged接口,类能很容易在WPF,Sliverlight和应用程序来给用户反映改变。

  • 向后兼容性
  •  当序列化你的对象到二进制中,很难去维护正确的版本,当你增加了一个新的属性给二进制类,或者更改了命名空间,对象将不能被再载入,data object 对象注意到这个问题,支持向后兼容性。
  • 验证

    这个类实现了IDataErrorInfo接口,,因此他可以验证数据对象检查错误,这样,不需要在类外面写验证代码。
  • 备份和恢复

    这个类实现了IEdiableObject对象接口,这样可以为对象创造一个状态,所有的属性能够被编辑,最终改变可以被提及或者回滚。

  • 4.1 使用类

这个类的使用非常简单,只需要创建一个类继承于ModelBase,如下

/// <summary>
/// MyObject class which fully supports serialization,
/// property changed notifications, backwards compatibility and error checking.
/// </summary>
#if !SILVERLIGHT
[Serializable]
#endif
public class MyObject : ModelBase<MyObject>
{
    /// <summary>
    /// Initializes a new object from scratch.
    /// </summary>
    public MyObject() { }

#if !SILVERLIGHT
/// <summary>
/// Initializes a new object based on <see cref="SerializationInfo"/>.
/// </summary>
/// <param name="info"><see cref="SerializationInfo"/>
//     that contains the information.</param>
/// <param name="context"><see cref="StreamingContext"/>.</param>
protected MyObject(SerializationInfo info, StreamingContext context)
    : base(info, context) { }
#endif
}

正如你在上面代码中所看到的,MyObject对象继承与ModelBase,并且提供了一个空的构造函数,但是也有一个构造函数用于二进制反序列化,上面的代码看起来复杂,但是这个事事用CodeSnppet来创建的,你只需要填写类的名称即可。

4.1.1 定义属性

为类定义属性也是非常简单,这个与依赖项属性类似,这样定义属性的优点是:

1,属性定义自定包括在序列化中,不需要制定复杂数据接口。

2,你能够为属性指定默认值,当类被构造或者没有在反序列化中发现(在属性被加入到一个存在类的情况)

3,ProperyData对象能够用于返回属性值,编译器可以检查错误,

4,你能够直接订阅改变观察,所有的属性自动支持INotifyPropertyChanged.

下面是字符串代码:

/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name
{
    get { return GetValue<string>(NameProperty); }
    set { SetValue(NameProperty, value); }
}

/// <summary>
/// Register the Name property so it is known in the class.
/// </summary>
public static readonly PropertyData NameProperty = RegisterProperty("Name", typeof(string), string.Empty);

一个注册的属性如果需要可以被序列化排除,当对象反序列化时,默认值可以在这种情况下使用。

4.1.2 引用类型的默认值

在许多情况下,引用类型的默认值在定义时是需要的,然而,你可能在依赖属性的理智中注意到这个行为,使用默认值的实例会导致异常行为。

下面是一个“常规”属性,用于定义属性集合

Default values for reference types

 

public static readonly PropertyData NameProperty = RegisterProperty("PersonCollection", typeof(Collection<Person>), new Collection<Person>());

然而,替代创建一个新的集合对象,仅仅一个集合会被创建在使用这个类,一个方案是将null作为默认值,创建这个集合的构造函数,一个更好的解决方案是重写RegisterProperty的回调参数。

 

public static readonly PropertyData NameProperty = RegisterProperty("PersonCollection", typeof(Collection<Person>), new Collection<Person>());

这样,每次新的值需要的时候,回调函数都会创建默认值,你将有对所有引用类型都用默认值。

4.2 提供的功能

ModelBase提供许多立即可用的功能,

INotifyPropertyChanged

所用使用RegisterProperty方法注册的属性自动的关注属性更改。

IDataErrorInfo

很容易使用SetFieldError和SetBussinessError方法设置字段和业务错误,也可以重写ValidateFields和ValidateBusinessRules方法。

IEditableObject

数据对象能够创建一个内部的备份和存储,使用IEditableObject接口

.

Serialization

如前面提到的很多次的,使用SavableModelBase,你能够简单的保存你的对象到stream(文件或者是steam)

记住这个类是不适合数据库传输的,有更好的办法去处理它(通过Entity Framework以及NHibernate,LLBLGenPro提供的ORM匹配)

时间: 2024-10-07 10:13:58

Catel帮助手册-Catel.Core:(4)数据处理的相关文章

Catel帮助手册-Catel.Core(6):日志管理

1,简介      从2.2版本开始,Catel使用了一个自定义的日志系统,这种方式,针对log4net的引用可以被移除,做这个修改主要是为了不强迫用户使用log4net,同时,log4net看起来很长时间不更新了,其他的日志系统如NLog看起来在增长,新的日志系统将允许许多基础的日志,这样,日志将将非常简单,并且如果他需要,真正的日志将被用户执行. 1.1 Log和ILog      所有的日志将通过ILog接口.这个接口被自动的注册到Catel中的所有对象上作为Log字段,ILog接口仅仅有

Catel帮助手册-Catel.Core:(5)依赖注入(ServiceLocator and TypeFactory)

1,简介 在Catel2.0之前,IOC容器内部使用的是Unity,然而,这就强制所有的用户在他的应用程序中使用Unity作为IOC容器,也需要这样划分库,从2.0以后,一个不同的技术被使用了,这个允许开发者可以使用他们自己悬着的IOC容器技术. 1.1在Ioc中不同的组件 在Catel中有许多不同的组件他们对于Ioc是非常重要的. ServiceLocator 该组件用于注册所有的类型,这个事真正的Ioc容器 TypeFactory 用于创建类型的组件,使用IServiceLocator来获取

Catel帮助手册-Catel.Core:(2)缓存处理

      缓存是用于提供应用程序执行效率的,应用程序大部分的花费都用于数据的获取,这些处理主要移动到网络上或者存储到硬盘中,但是某些数据不太会改变,并不需要每次都同步.     因此,为了提高应用程序的执行效率,找到一个很好的方法来处理这些不太改变的数据库,Catel使用了一个 CatchStorage<TKey,TValue>的类,注意,第一个泛型的参数表示的是关键字的类型,第二个泛型的参数是要存储的值的类型,就像Dictonary<Tkey,TValue>.但是CatcheS

Catel帮助手册-Catel.Core:(1)参数检查

  我们检查方法是否正确,一般是返回对错,或者是是否抛出一个异常,大部分人不检查异常的正确性,那么这种错误在很深的堆栈中,很难查看. Catel与一般的检查方法不同,一般是使用   public void CheckForException(object obj) { if (obj == null) { throw new ArgumentNullException("obj"); } }   然而,Catel会记录所有的行为,因此开始的检查方式如下: public void Che

Catel帮助手册-Catel.Core:(3)配置说明

      Catel可以让你更方便的配置所有的平台 下面的表格解释了每个平台使用何种技术来获取和存储配置值. 平台 技术 .NET ConfigurationManager.AppSettings Sliverlight IsolatedStorageSettings.ApplicationSettings WinRT ApplicationData.Current.LocalSettings PCL 不支持   1 从配置中获取值    使用如下代码从配置中获取值: var configur

Catel帮助手册-Catel.Core:(5)异常处理

  在Catel中使用异常处理时,创建一个异常处理策略和执行代码是安全的,不需要人工检查所有的异常类型,Catel通过IExceptionService方法来处理这个技术.   1,设置IExceptionService      注册一个异常到服务中让Calte知道他如何被获取,是很重要的,服务会处理加入到IExceptionService中的异常.      下面是注册一些异常以及他们如何被获取的例子,当FileNotFoundException异常发送时,它会给用户显示消息,对于其他的异常

20个为前端开发者准备的文档和指南

20个为前端开发者准备的文档和指南 来源:codeceo 发布时间:2016-07-27 阅读次数:358 0 是时候重新学习了!和以前一样,我收集了很多不同的学习资源,包括学习指南,学习文档,和其他有用的网站来帮助你在前端开发的不同领域里快速地进入状态. 所以请尽情享受我们的文档和指南系列的第九部分,并且不要忘了在评论区让我知道任何我没有找到的. 1. JavaScript Standard Style(JavaScript标准样式) 链接:http://standardjs.com Java

《iOS 7 应用开发实战详解》

<iOS 7 应用开发实战详解> 基本信息 作者: 朱元波    管蕾 出版社:人民邮电出版社 ISBN:9787115343697 上架时间:2014-4-25 出版日期:2014 年5月 开本:16开 页码:382 版次:1-1 所属分类:计算机 > 软件与程序设计 > 移动开发 > iPhone 更多关于>>><iOS 7 应用开发实战详解> 编辑推荐 新版本 全面讲解了iOS 7开发的各种技术 热门技术 基本控件.数据存储.多场景处理.界

Catel框架类库说明-Catel.Core

1,参数检查 我们检查方法是否正确,一般是返回对错,或者是是否抛出一个异常,大部分人不检查异常的正确性,那么这种错误在很深的堆栈中,很难查看. Catel与一般的检查方法不同,一般是使用   public void CheckForException(object obj) { if (obj == null) { throw new ArgumentNullException("obj"); } }   然而,Catel会记录所有的行为,因此开始的检查方式如下: public voi