• 通过 ViewState 保存 SelfTracking Entities


    如果你希望能够在 ViewState 中保存 Self-Tracking Entities 对象,那么,将会遇到不能序列化的问题。

    问题的原因在于 ViewState 通过将对象序列化之后通过隐藏域保存在网页中,所以,希望通过 ViewState 进行状态管理的对象必须支持序列化。

    但是 Self-Tracking Entities 中生成的类没有序列化的标签,所以,导致使用失败。

    幸运的是,Self-Tracking Entities 是通过 T4 - Text Template Transformation Toolkit 来生成代码的。

    关于 T4 - Text Template Transformation Toolkit  可以参考我的另外一篇文章。VS2010 中的代码生成器 T4 - Text Template Transformation Toolkit

    默认的  Self-Tracking Entities  模板中没有包含我们需要的标记说明来支持序列化,好消息就是我们可以简单的编辑一下  Self-Tracking Entities  的  T4 模板就可以了。

    我们需要这几步就可以:

    1. 增加 [Serializable] 标签到实体,复杂类型和集合类

    2. 为字典集合类增加必须的序列化构造器

    3. 为实体和复杂类型的 OnDerserializedMethod  方法增加一些代码,当一个实体被反序列化的时候来注册变化的跟踪事件

    但是在  Silverlight 中还没有二进制的序列化。所以,如果你做了上面第1 和第 2 步的修改,那么,在 Silverlight 中将不能通过编译。

     

     Self-Tracking Entities  在你的项目中加入了两个模板,其中一个用来生成 ObjectContext ,另外一个用来生成实体,我们需要修改的内容就在第二个用来生成实体的模板中。

    第一件事就是给所有的类增加 [Serializable] 标签 以支持序列化。

    先找到 37 行,增加 [Serializable] 后,应该如下所示:

    37 [Serializable]
    38 <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#><#=entity.BaseType == null ? "" : ""#>IObjectWithChangeTracker, INotifyPropertyChanged
     

     后面的修改依次如下。

    1403: [Serializable]
    1404public class TrackableCollection<T> : ObservableCollection<T>
    1405: {
    1428: [Serializable]
    1429public class ObjectChangeTracker
    1430: {
    1650: [Serializable]
    1651public class ObjectsAddedToCollectionProperties : Dictionary<string, ObjectList>
    1652  { }
    1655: [Serializable]
    1656public class ObjectsRemovedFromCollectionProperties : Dictionary<string,
           ObjectList> { }

    1660: [Serializable]
    1661public class OriginalValuesDictionary : Dictionary<string, Object> { }

    1665: [Serializable]
    1666public class ExtendedPropertiesDictionary : Dictionary<string, Object> { }
    1669: [Serializable]
    1670public class ObjectList : List<object> { }

    序列化构造器

    下一步,我们要确认所有从 Dictionary<> 派生的类都完全支持序列化。

    由于 Dictionary<> 类通过实现接口  ISerializable 来实现了自定义的序列化,所以,所有派生自 Dictionary<> 的类必须有一个特制的用于反序列化的构造函数。

    并不需要我们为构造函数增加什么代码,仅仅需要有构造函数来支持  Dictionary<>  的反序列化。这里有四个类需要做修改。

    ObjectsAddedToCollectionProperties

     1651public class ObjectsAddedToCollectionProperties : Dictionary<string, ObjectList>
     1652: {
     1653:     public ObjectsAddedToCollectionProperties() { }
     1654:
     1655:     protected ObjectsAddedToCollectionProperties(SerializationInfo info,
     1656:                                                  StreamingContext ctx) 
     1657:         : base(info, ctx)
     1658:     { }
     1659: }

    ObjectsRemovedFromCollectionProperties 类

     1664public class ObjectsRemovedFromCollectionProperties : Dictionary<stringObjectList>
     1665: {
     1666:     public ObjectsRemovedFromCollectionProperties() { }
     1667:
     1668:     protected ObjectsRemovedFromCollectionProperties(SerializationInfo info, 
     1669:                                                      StreamingContext ctx) 
     1670:        : base(info, ctx)
     1671:    { }
     1672: }

    OriginalValuesDictionary

     1677public class OriginalValuesDictionary : Dictionary<string, Object>
     1678: {
     1679:     public OriginalValuesDictionary() { }
     1680:
     1681:     protected OriginalValuesDictionary(SerializationInfo info,
     1682:                                        StreamingContext ctx) 
     1683:         : base(info, ctx)
     1684:     { }
     1685: }

    最后,ExtendedPropertiesDictionary 类

     1690public class ExtendedPropertiesDictionary : Dictionary<string, Object>
     1691: {
     1692:     public ExtendedPropertiesDictionary() { }
     1693:
     1694:     protected ExtendedPropertiesDictionary(SerializationInfo info, 
     1695:                                            StreamingContext ctx) 
     1696:         : base(info, ctx)
     1697:     { }
     1698: }

    事件的处理

    由于在进行二进制序列化的时候不会序列化事件的处理,所以,在反序列化之后,我们可以通过 OnDeserialized  方法来执行一些我们自己的代码完成这个工作。

    为了给实体增加这些工作,我们可以在模板中找到 OnDeserializedMethod  方法,然后增加三种重要的事件处理:

    复杂类型事件处理

    双向连接的集合属性的事件处理

    级联删除的事件处理

    将原来的 OnDeserializedMethod 方法直接用下面的替换掉

    [OnDeserialized]
    public void OnDeserializedMethod(StreamingContext context)
    {
        IsDeserializing 
    = false;
        ChangeTracker.ChangeTrackingEnabled 
    = true;
    <#
    // Hook up ComplexType property event handlers
    foreach(EdmProperty edmProperty in entity.Properties
        .Where(p 
    => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
    {
    #
    >
        
    if (<#=code.FieldName(edmProperty)#> != null)
        {
            ((INotifyComplexPropertyChanging)
    <#=code.FieldName(edmProperty)#>)
                 .ComplexPropertyChanging 
    -= Handle<#=edmProperty.Name#>Changing;
            ((INotifyComplexPropertyChanging)
    <#=code.FieldName(edmProperty)#>)
                 .ComplexPropertyChanging 
    += Handle<#=edmProperty.Name#>Changing;
        }
    <#
    }
    // Hook up Collection property event handlers
    foreach (NavigationProperty navProperty in entity.NavigationProperties
        .Where(np 
    => np.DeclaringType == entity))
    {
        
    if (navProperty.ToEndMember.RelationshipMultiplicity ==
                                              RelationshipMultiplicity.Many)
        {
    #
    >
        
    if (<#=code.FieldName(navProperty)#> != null)
        {
            
    <#=code.FieldName(navProperty)#>.CollectionChanged -= Fixup<#=navProperty.Name#>;
            
    <#=code.FieldName(navProperty)#>.CollectionChanged += Fixup<#=navProperty.Name#>;
    <#
            
    if (ef.IsCascadeDeletePrincipal(navProperty))
            {
    #
    >
            
    // This is the principal end in an association that performs cascade deletes.
            
    // Add the cascade delete event handler for any entities that are 
            
    // already in the collection.
            foreach (var item in <#=code.FieldName(navProperty)#>)
            {
                ChangeTracker.ObjectStateChanging 
    -= item.HandleCascadeDelete;
                ChangeTracker.ObjectStateChanging 
    += item.HandleCascadeDelete;
            }
    <#
            }
    #
    >
        }
    <#
        }
    }
    #
    >
    }

    完成上面的这些修改之后,你的 self-tracking entities 应该可以进行二进制序列化了,也就可以通过 ViewState 进行状态管理。

    在 Jeff Derstadt 的文章 Using Binary Serialization and ViewState with Self-Tracking Entities 中,还给出了一个已经修改好的模版文件,这是链接地址:完成的模版

    这篇文章来自:Jeff Derstadt 的文章,这是原文的链接:http://blogs.msdn.com/b/adonet/archive/2010/05/26/using-binary-serialization-and-viewstate-with-self-tracking-entities.aspx

  • 相关阅读:
    java匿名对象
    Java面向对象详解
    Java语言基本语法
    Win7下JDK环境变量的设置
    LeetCode-Shortest Word Distance
    LeetCode-Count Complete Tree Nodes
    LeetCode-Palindrome Pairs
    LeetCode- Implement Trie (Prefix Tree)
    LeetCode-Lowest Common Ancestor of a Binary Tre
    LeetCode- Binary Tree Longest Consecutive Sequence
  • 原文地址:https://www.cnblogs.com/haogj/p/1757449.html
Copyright © 2020-2023  润新知