This design document was written in March to attend the company's R & D summit. I was confident, but I was not shortlisted. Now I think it is useless, so I will post it and look forward to communicating with park friends.
The document is a little long and is not all posted on the blog. If you are interested, you can download the PDF file in the attachment.
Attachment: " -- System Design Description
============================ Separation line ============================
Directory
Preface... 4
1 Background and requirements... 5
1.1 product 721 custom development needs... 5
1.2 entity dynamic column... 6
1.3 separating read-only/view attributes... 6
1.4 improve framework performance... 6
1.5 supports WPF binding... 6
1.6 other requirements... 7
2 analysis... 8
2.1 main functional requirements... 8
2.2 non-functional requirement analysis... 8
2.3 constraints... 9
2.4 risks... 9
3. Design Scheme... 10
3.1 some decisions... 10
3.2 risk point verification... 10
3.2.1 supports WPF binding... 10
3.2.2 key performance points... 12
3.3 solution description... 12
3.3.1 structure description... 13
3.3.2 related UML diagram... 14
3.3.3 how to support requirements... 18
3.4 key implementation details... 18
4 design verification... 24
4.1 Functional Requirement verification... 24
4.2 WPF binding verification... 24
4.3 performance verification... 25
5 user manual... 25
5.1 use cases (unit test)... 25
5.1.1 default attribute value... 26
5.1.2 force replacement of attribute values... 27
5.1.3 cancellation and forced replacement of attribute values... 27
5.1.4 canceling the setting of referencing object attributes... 28
5.1.5 attribute change event... 29
5.1.6 product 721 extended attributes... 30
5.1.7 Interface Generation for all extended attributes... 31
5.1.8 usage of read-only attributes... 31
5.1.9 usage of read-only extended attributes... 32
5.1.10 runtime dynamic attributes (Dynamic columns)... 33
5.1.11 serialization... 34
5.1.12 WPF binding verification... 35
5.1.13 extended attribute ORM verification... 35
5.1.14 object status attributes... 35
5.2 code generation-codesnippets. 36
5.3 Other questions... 37
5.3.1 pay attention to writing CLR attributes of extended attributes... 37
5.3.2 when to use property extension and when to use inheritance extension ?... 38
Preface
In product line development, supporting product customization is an important part of product large-scale development. A very important part of customization is the customization of attribute values, including the addition, deletion, modification of attribute values and the customization of interfaces corresponding to attributes. Because the product's extension scheme for property values has always been completed using the class inheritance scheme, there are many problems in the product:
L one of the most important problems is that sometimes one customer cannot provide two optional feature packages. To solve this problem, developers have to do a lotCodePort the code of the Optional package to the main version, resulting in excessive temporary code and high maintenance costs.
L In addition, our product is based on entity development. In order to meet the needs of dynamic columns, we finally decided to use the data table mode for writing, which also resulted in a large number of repeated codes, low developer development efficiency.
Based on these historical issues, we have designed a brand new property system. After the system is designed, it solves many historical issues and brings many unexpected values. For example:
L supports simple extension of attributes in custom development.
L support more simple implementation of dynamic attributes of domain entities (Dynamic columns in the interface, originally required 100 lines of code, now only 20 lines are supported .)
L view attribute separation (better maintainability)
L attribute performance improvement (Performance Improvement)
L reduces serialized data (improved transmission efficiency and improved performance)
L unified attribute interfaces (the platform provides more powerful functions)
This design is to refactor the historical code, but it is essentially to design a completely independent sub-system. This article describes how the entire design is completed from the perspective of requirements, analysis, solutions, implementation, and verification. Finally, the System user manual is provided to help developers with their daily application.
Note:
In this document, the "entity extension Property System" is referred to as EMPs for convenience. (Entity managed property system, indicating the entity-managed Property System)
In addition, the version number mentioned in this article: the historical OEA version is 2.5. After the EMPs is upgraded, the OEA version is 2.6.
1. Background and requirements
This section describes the background of the system design and the list of requirements. These requirements are collected and accumulated in the early stage. The following describes the main requirements:
1.1 product 721 custom development needs
Several products of the Department are developed based on the OEA platform. The OEA platform mainly solves the problems of custom development in product development mode and how to improve development efficiency during product development.
(For more information about the 721 concept in product development and the custom design in OEA, See OEA framework-based custom design (3) "plug-in-type" DLL ". For more information about OEA, See OEA framework demo-faster than prototype product development.)
In custom development, the main problem solved is how to expand the products in the main version in the custom version. Various extensions generally rely on the underlying metadata, which describes the entire system. When we modify the metadata, the entire applicationProgramIt also changes accordingly. The extension of these products can be divided into: module-level extension, entity-level extension, and attribute-level extension. The extension of the module is not discussed here.
Attribute extension first: We generally perform the following extension for the attributes of classes defined in the product: add an attribute, delete an attribute, and modify an attribute. (So the extension does not just mean adding .) Adding a property means that we need to add an additional Property for the defined class. This property can be mapped to the database and displayed on the product interface, the behavior is consistent with the directly defined attribute. Deleting a property means that the database does not have any corresponding fields and the interface is no longer displayed. Modifying an attribute generally only modifies the metadata of an attribute, for example, modifying the field metadata mapped to the database and modifying the metadata of the columns displayed on the interface; these modifications have actually been solved in the metadata design scheme. For details, refer to: OEA-based custom design (1) general design, custom design based on OEA framework (ii) metadata design, and custom design based on OEA framework (iii) Plug-In DLL.
Object extensions can generally be implemented through inheritance methods. When a new subclass is inherited, it can be used in metadata to overwrite the original parent class. In some cases, we also expand some aggregate parent-child relationships for a class. For example, we can expand the list of related contracts for a construction project, only the project interface is displayed, and the corresponding contract list of each project is displayed immediately. Although this type of parent-child relationship aggregation is added at the entity level, it is essentially adding a one-to-multiple relationship to the object. That is to say, the extension of this object can be converted to attribute extension, that is, an attribute of one-to-multiple relationship can be extended on the basis of the original object.
Based on the above analysis, we know that a scalable property system is almost the most basic infrastructure for running custom software products.
In OEA versions earlier than 2.6, property extensions are implemented in inheritance mode. Simply put, it inherits the object to be extended, adds new attributes, and replaces the original class with this object. This scheme is mainly used to add attributes, but the deletion and modification of attributes are implemented by modifying the metadata of attributes. This method causes many problems: the attribute deletion only deletes the interface, and the database and runtime entity also has this attribute; the Attribute Modification cannot modify the behavior code in the attribute; the following describes the disadvantages caused by attribute addition:
It is often necessary to extend one or two attributes to a class, but now it can only inherit the subclass, hide the parent class, or directly overwrite the parent class, which is more complicated to use. At the same time, there are more types, the Learning and maintenance costs of developers increase.
More importantly ,. the restriction of the CLR single inheritance system in. Net makes it impossible to implement such extension through inheritance: two independent extension packages "2" Expand the main package "7" in an optional form, that is to say, in product 721 custom development, two "2" extension packages are two separate assemblies, but we cannot use them at the same time due to single inheritance restrictions. In this case, our current processing method is to put both "2" packages into the master package, and use metadata to hide unwanted features, this implementation method is temporary and incorrect.
1.2 entity dynamic Columns
In software development, dynamic columns are often required: columns of data in tables are automatically generated based on the data itself, this is basically impossible for a system developed based on the domain entity type and non-dynamic technical framework. Therefore, the application may have another shortcut. The datatable is used to re-assemble the data and then display the data. This causes the two modes to exist in one system at the same time, and the same code will appear again, increasing the maintenance cost. The interface code is inconsistent, which also makes it difficult to automatically generate the interface.
If we have extended attributes, we can expand various new attributes on any entity, and the interface becomes a "dynamic" column accordingly.
1.3 separate read-only/view attributes
Some read-only attributes are often added to the object design. The value is calculated based on the current value of the object. In OEA, objects are designed as distributed objects (in short, a set of entity code is reused between the client and the server. See the csla Framework Design book "Expert C #2008 Business Objects".), These distributed objects are directly bound to the interface. Many read-only view attributes are often added for interface display, which leads to too many view attributes. These attributes are mixed in the code of domain entities, causing code contamination, increase maintenance difficulty.
If the extended attribute is available, we can put the read-only attribute into a separate class to expand the object. In this way, you can get code with a more concise and clear structure.
1.4 improve framework performance
For framework development, it is often necessary to uniformly process object attributes in the framework to provide powerful functional support to the application layer. If you use a general entity design, you must use reflection to obtain and set attribute values. A large number of attribute value operations mean poor performance. If you have managed attributes, you can use the attribute API that is consistent with the application at the framework level to operate the attributes. Instead of using reflection, the speed can be greatly improved.
1.5 supports WPF binding
In general, when we use WPF to bind, they are all directly bound to the CLR hosting property. However, if you use extended attributes, not all attributes will have a CLR property encapsulate. Therefore, these extension attributes must support WPF binding.
1.6 Other requirements
LSupport property anti-Extension
During product 721 development, you often need to delete the attributes extended for "7" in "2" in the "1" custom version. In this case, you need to support anti-extension of attributes (or anti-registration ).
LGet attribute value source
Because the objects in the OEA framework are distributed objects, we often need to identify the source of the attribute values when the object attributes change: database, UI interface, or other code in the program.
LCustom serialized data
After object attributes are managed by the framework, serialization of various data formats can be easily realized.
LEvent Notifications such as property value verification, force, and change notifications must be supported.
LMetadata overload
All actions of an attribute are stored in the metadata in the form of callback. Metadata can be overloaded. In this way, the subclass will override these actions. At the same time, we can re-Customize these behaviors for attributes during product customization.
Finally, let's take a look at the demand overview chart in the brain chart document "Object extended attributes scheme analysis brain Chart". These requirements are not supported in previous versions:
Figure 1. Object extended attribute Requirement List
2 Analysis
The preceding requirements have been clarified. So here, we need to analyzeMain requirements, constraints and related risks. (For the whole process of Framework Design, refer to this article.Article: Summary of framework module design experience.)
2.1 main functional requirements
In fact, the requirements have been divided by priority in Figure 1, and the subsequent design will focus on these requirements. Among them, the most importantFunctional requirementsIs the following three. The design goal is to achieve at least the following three requirements, and other requirements are implemented based on priority as much as possible.
L721Property extension in custom development
LProperty hosting (managed by Framework)
This means that the upper-layer framework must be provided with the function of uniformly maintaining attribute values.
LDynamic Columns
2.2 non-functional requirement analysis
LRuntime Performance
Entity attributes can be said to be the most important part in Entity design. Its performance is related to every attribute of every entity in the system. These attributes are directly related to the application performance. Simply put, if the attribute system is slow, the performance of upper-layer applications will inevitably be slow. In other words, property system code development is very performance-sensitive and requires caution in core code.
In version 2.5, The OEA framework mainly uses the native CLR attribute system in. NET + the attribute system in the csla open-source framework. The main purpose is to support unified attribute management. This design can bring many new functions and support to the system. In addition, the attribute performance of the original system does not constitute the performance problem of application layer development. Therefore, certain performance consumption is acceptable.
The requirements for this item are:
The same Code can be used for property testing and comparison with the historical property system. The time consumed cannot exceed 120% of the original time.
Relatively simple and strict.Once this option is not met, the entire design cannot be used.
LIndependence
Although the object extension property system is an important part of the OEA framework, the requirements for hosting and extension properties are often met during development. Therefore, we need to design the object extension attribute system as an independent DLL so that it can be used in a non-OEA platform environment.
LScalability
The extensibility of EMPS does not refer to the extendibility of attributes brought by the system (which is actually the functional requirement of EMPs), but to the extensibility of the property system itself.
Currently, the OEA framework uses product metadata as the infrastructure of the entire framework. That is to say, the OEA framework has the function of managing all metadata in an application. As shown in the requirement list in Figure 1, EMPs also needs metadata support, such as the default attribute value. However, independence requires that EMPs be designed as a completely independent module, that is, EMPs is completely independent from OEA. How can metadata of these attributes be stored using OEA? This is also an extension point that needs special consideration in the EMPs design process.
LEase of use
This is a non-functional requirement that the framework design must consider.
2.3 Constraints
LORMFunction Modification
The original oea orm supports oeaorm and entityframework4.1 (codefirst) modes. However, both of them currently support only CLR attribute ing. The extended attributes do not have the CLR property wrapper, but these extended attributes also need to be mapped to the database.
That is to say, if EMPs development is complete and new extended attributes need to be mapped, the current oeaorm module must be modified. At the same time, entityframework4.1 is no longer supported (efcodefirst is mapped based on CLR attributes ).
LCompatibility with original property Functions
The attribute used by OEA in version 2.5 is mainly the native CLR attribute system in. NET + the attribute system in the csla open-source framework. A lot of code has been written in these attributes. The get accessors of attributes and the code in the Set configurator are varied. These must be fully compatible with the new property system. Otherwise, service functions must be faulty.
LA large number of historical code modifications
Because this design is essentially a reconstruction of previous versions, and up to now, product development has produced tens of thousands of lines of historical code, among which there are thousands of entity attributes. Restructuring the underlying design will inevitably cause many changes while ensuring that the application-layer API remains unchanged. At the same time, many bugs may occur. This is a constraint that must be considered.
2.4 risks
LAttribute Performance
It is known from the descriptions of non-functional requirements that performance is crucial. Whether the entire design is available. However, the final module performance is hard to be measured during design. To avoid this risk, use the following solution: analyze the key performance impact points of the historical attribute system. After the design draft is complete, theoretically, check whether these key points can run well in the new property system.
LSupports WPFBind
This is a technical difficulty.
Currently, we only use the scheme of directly binding CLR attributes in WPF. How to enable us to expand the extended attributes in a customized version of the program also supports WPF binding has become a technical challenge.
The avoidance of this is very simple. Before the entire design starts, we should first analyze the internal mechanism in the WPF binding to solve this problem before we can start other designs.
3. Design Scheme 3.1 some decisions
The design of the system is complicated. Therefore, we made a decision on compatibility constraints:
During the design process, we should try to ensure that the functions are compatible with the original property system and the interfaces are consistent. However, this interface is not compatible when it is not compatible or cannot be consistent. However, these incompatible design points must be recorded and modified one by one after the design is complete. If the changes are large, the reconstruction tool in the group is used.
3.2 risk point verification 3.2.1 supports WPF binding
After checking msdn and the searched network resources, it is found that the binding mechanism in WPF supports binding the datatable data table type, while the fields in the table are dynamic and change according to the changes in the result data. So as long as you know how datatable is supported by WPF binding, EMPs can also use the same mechanism for binding.
The following is an analysis of the datatable binding mechanism in WPF:
Figure 2. datatable in WPF supports Core Type Analysis
Figure 3. flowchart of generating view model for datatable in WPF
The key point is that datatable implements the ilistsource interface, constructs a dynamic view dynamic type datarowview, and implements icustomtypedescriptor. (For detailed procedures, see this article: OEA extended attribute system-Design Analysis for any adaptation to WPF binding, and the documents in this series: Design Analysis for any adaptation to WPF binding.)
After figuring out the entire design and creation process, we can actually support this mechanism when designing EMPs.
3.2.2 key performance points
We need to analyze how the property system (csla managed property system) in the historical framework ensures the performance while hosting the property?
In fact, the core focus of the attribute is to use strong fielddata <t> to store each attribute and store it using an array of fixed-length attribute values:
Private ifielddata [] _ fielddata;
The advantage of this is that the strong type ensures no binning and unboxing operations, and the fixed length array supports searching for the specified attribute with the complexity of O (1:
However, the premise for searching properties is that the attribute value array is fixed and the number of attributes of an object type has been completely determined during the compilation period. In other words, a fixed number of attributes must be known during array initialization, which violates the property scalability requirement and is also the reason why the attribute system is difficult to expand.
Of course, it is not impossible to make major changes to it. However, considering that csla is an open-source framework that meets our needs, there is a big difference between it and our needs. The code is too bloated to implement the functions we need, it is better to create a new managed property framework that fully meets the requirements to make major changes to it.
After the previous analysis, we can think that to get a high-performance hosted property system, it is best to use the "strong type storage property value" and "Fixed Length array" solution. But how can we support attribute extension? "Dividing attribute definition period" is a good solution. This solution will be described in detail in the subsequent subject design.
3.3 solution description
The whole design draws on the csla hosting attribute and the WPF dependency attribute design, and then constructs our own property system:
3.3.1 Structure Description
Figure 4. EMPs Structure Description
The brain chart is relatively simple. For details, refer to brain Chart "extended attributes Scheme". Here is a brief description:
LStatic Structure
In general, the static structure is relatively simple and mainly divided into two layers. The underlying layer is the abstract attribute metadata provision subsystem, while the other layer is the EMPs core built on the former: extended attribute subsystem during runtime.
Abstract attribute Metadata Extraction provides a system for metadata storage and abstraction. Later, it can be adapted to the metadata storage module in OEA.
The core EMPs implements the entire managed attribute. It will be highlighted in the form of a class chart later.
LDynamic Structure
The concept of attribute lifecycle is put forward here. The lifecycle of an attribute specifies the period in which the attribute is defined (or unregistered) (it may be called a correct definition period .), The compilation, start, and run phases are provided here.
L compilation phase
The attributes defined in this phase mainly include general attributes written in code and extended attributes. Of course, it also includes some extended attributes written in the "2" and "1" extension packages for the "7" package entity class.
Specify the corresponding metadata when defining an attribute.
L start time
In this phase, the compilation phase attributes and their corresponding metadata are modified in a custom way.
L Runtime
This stage is mainly used to append dynamic attributes during runtime.
These dynamic attributes are generally only used for display, and they will affect the generation of the interface. The extension and deletion of attributes must be confirmed before the control is generated. Otherwise, no corresponding Column exists on the interface.
Because the interface generation is affected, You need to specify the interface metadata in the OEA framework. If this parameter is not specified, the default metadata is used. However, the metadata design will be completed in the OEA framework and has nothing to do with the EMPs design.
The additional attributes extended in this phase do not have any relationship with the server program. That is to say, you do not need to define server metadata such as ORM for these extended attributes. Of course, the data of these attributes does not need to be serialized and then transmitted on the network.
The main reason for dividing these cycles: Determines the length of the attribute list during compilation and startup of an object. This is because attributes that have been defined, modified, or customized during the compilation and startup phases will not be changed when the program enters the runtime. These attributes occupy more than 95% of application development. Therefore, as long as we know the length of the attribute during the compilation phase, it means that we can use the array retrieved by O (1) to store it, instead of the slower list/hashtable, which guarantees the performance of these attributes. For runtime attributes, although the length cannot be fixed and changes according to the business scenario, the performance can be ignored because the usage is small.
3.3.2 related UML diagram
For a complete UML diagram, see entity extension attributes UML design diagram. The following describes the key points.
Figure 5. Outline Design of extended attribute core Class Structure
This is the outline design of the core class structure for implementing extended attributes, which mainly includesManagedpropertyobject,Managedproperty,Managedpropertyfield,Managedpropertymeta. Because it is a summary design drawing, the methods, attributes, and other relative implementations of the system after the completion of the comparison, certainly not complete, but its role is mainly to illustrate the core idea of the entire design. Where:
ManagedpropertyIndicates a managed property. Each time a managed property is defined, the system generates an object of this type for marking. This tag is required for retrieving and setting attribute values.
ManagedpropertymetaIndicates the managed property metadata, which provides a lot of information, such as the default value, whether it is read-only, and the logical callback of attribute change; these metadata have a great impact on the logic for obtaining and setting attribute values.
ManagedpropertyfieldIndicates the value of a managed property in an object. In fact, this class will be defined as a generic class in later implementation. In this way, the storage of values is not an object but a strong type, and The binning operation is not required.
ManagedpropertyobjectIndicates the object base class (entity) with managed attributes, which definesManagedpropertyTo obtain and set the value, so that the object can obtain and store various values like a common object. At the same time, it also provides interfaces for unified processing of all managed property values. These interfaces are rarely used in application development and are mainly used by upper-layer frameworks. The upper-layer framework can use these interfaces to complete the following framework tasks: unified object Value copying, unified serialization, and retrieval of specific types of values. Such value acquisition and setting speeds are as follows, it is far faster than reflection.
Figure 6. Extended property warehouse summary design diagram
This figure shows that the managed attributes of the entire system are the singleton objects in the system.ManagedpropertyrepositoryFor management purposes, in order to provide a more convenient query function for the upper layer and facilitate storage, it usesTypeindicators Class to store the attribute list of an object type.TypeindicatorsThis class is also responsible for providing query for the upper layer: A list of attributes defined by a type, a list of associated attributes defined by a type and all attributes defined by all its parent classes. At the same time, all the attributes in this class will generate the index of the attribute in the type. In this way, you can use this index to search for the attribute value in the attribute value array when obtaining the attribute value.
Figure 7. Extended property metadata summary Design Drawing
As mentioned above, in order to ensure the independence of EMPs, We need to abstract the Data Acquisition Scheme of managed property metadata.Ipropertymetaprovider Is the abstract metadata provider interface. The upper-layer OEA framework will implement its own provisionerOeapropertymetaproviderAnd use the information in the Metadata module (In the exampleOeapropertymetaTo provide metadata for managed properties.
Figure 8. Summary Design of WPF binding with extended property entities
This picture looks familiar? Yes, it is similar to the class chart in figure 2 that WPF supports datatable binding. Mainly letEntitylistImplement the ilistsource interface and addEntityviewClass implementationIcustomtypedescriptorIn this way, you can bind dynamic attributes to WPF.
3.3.3 how to support requirements
After reading the main design scheme and class diagram, we need to consider whether the whole scheme can support all the requirements mentioned above. Is to analyze the support of the entire requirement. For more information, see entity extension attributes analysis brain chart.
Figure 9. support analysis of the design scheme on the demand.
3.4 key implementation details
After the requirement support analysis, a design review meeting will be held to find that such a scheme can meet almost all the requirements. In this way, we will enter the implementation stage. The implementation process focuses more on the detailed design. This document selects a part of the key points.
First, let's take a look at the code structure of the core part of the final code:
Figure 10. Core code structure
The implementation and design of the entire structure are almost the same. Next, describe some important code:
L first, get and set the property value in managedpropertyobject:
As mentioned in the previous design scheme, this class serves as the base class of all entity classes and provides value acquisition and setting. In fact, this class puts the management of attribute values into an internal class.ManagedpropertyobjectfieldsmanagerMedium:
And proxy related operations to this class:
WhileManagedpropertyobjectfieldsmanagerThe core code of these logics is implemented. Its private fields are defined as follows:
We can see that the attribute values in the compilation and startup phases are stored separately from those in the runtime. The former uses arrays and constructor initialization, while the latter is serialized only when needed. Also noted that it inherits fromCustomserializationobjectSo that the entire Attribute Value List can be customized for serialization. Below, yesGenericAttribute Value acquisition and setting logic:
Internal tpropertytype getproperty <tpropertytype> (managedproperty <tpropertytype> Property)
{
VaR usedefault = true;
Tpropertytype result = default (tpropertytype );
If (property. isreadonly)
{
Result = (property as managedproperty <tpropertytype>). providereadonlyvalue (this. _ owner );
Usedefault = false;
}
Else
{
If (property. lifecycle = managedpropertylifecycle. compileorsetup)
{
VaR field = This. _ compiledfields [property. typecompiledindex] As managedpropertyfield <tpropertytype>;
If (field! = NULL)
{
Result = field. value;
Usedefault = false;
}
}
Else
{
If (this. _ runtimefields! = NULL)
{
Imanagedpropertyfield F;
If (this. _ runtimefields. trygetvalue (property, out f ))
{
VaR field = f As managedpropertyfield <tpropertytype>;
Result = field. value;
Usedefault = false;
}
}
}
}
VaR meta = property. getmeta (this );
If (usedefault) Result = meta. defaultvalue;
Result = meta. coercegetvalue (this. _ owner, result );
Return result;
}
Internal void setproperty <tpropertytype> (managedproperty <tpropertytype> property, tpropertytype value, managedpropertychangedsource source)
{
Forcenotreadonly (property );
VaR meta = property. getmeta (this );
Bool cancel = meta. raisepropertychanging (this. _ owner, ref value, source );
If (cancel) return;
VaR hasoldvalue = false;
Tpropertytype oldvalue = default (tpropertytype );
Managedpropertyfield <tpropertytype> Field = NULL;
// The code in this if block: searches for or creates the field of the corresponding property, and records possible historical values.
If (property. lifecycle = managedpropertylifecycle. compileorsetup)
{
Field = This. _ compiledfields [property. typecompiledindex] As managedpropertyfield <tpropertytype>;
If (field = NULL)
{
// Whether it is the default value or not, it is stored.
// The default value does not need to be detected, which is faster, but wastes some small space.
// Check the default value, which is implemented in the getnondefaproperpropertyvalues method.
Field = property. createfield ();
This. _ compiledfields [property. typecompiledindex] = field;
}
Else
{
Oldvalue = field. value;
Hasoldvalue = true;
}
}
Else
{
If (this. _ runtimefields = NULL)
{
This. _ runtimefields = new dictionary <imanagedproperty, imanagedpropertyfield> ();
}
Else
{
Imanagedpropertyfield F;
If (this. _ runtimefields. trygetvalue (property, out f ))
{
Field = f As managedpropertyfield <tpropertytype>;
Oldvalue = field. value;
Hasoldvalue = true;
}
}
If (field = NULL)
{
Field = property. createfield ();
This. _ runtimefields. Add (property, field );
}
}
Field. value = value;
If (! Hasoldvalue) {oldvalue = meta. defaultvalue ;}
If (! Object. Equals (oldvalue, value ))
{
// Events in Meta
VaR ARGs = meta. raisepropertychanged (
This. _ owner, oldvalue, value, Source
);
// Event
This. _ owner. raisepropertychanged (ARGs );
}
}
As you can see, during compilation, attributes are mainly stored through a one-dimensional array. every element in the array is a strongly typed generic object managedpropertyfield <tpropertytype>.
In addition, note that this class provides the same non-generic interface:
The non-generic method is mainly provided for the last framework, which mainly considers the performance consumption of The binning operation. (For the underlying framework design scheme of interfaces and generic classes, see refactoring practices: Experiencing the power of interfaces (1) and refactoring practices: Experiencing the power of interfaces (2) .)
The getproperty and setproperty methods are the two most performance-sensitive methods. They must be implemented with caution. Each method called internally, such as managedproperty. getmeta (managedpropertyobject owner) and managedpropertymetadata. raisepropertychanged and so on must also be specially optimized. We need to consider packing and unpacking, property retrieval, and not constructing redundant objects. For specific code design, refer to the Code in the actual project and do not describe it too much here.
L The method for registering attributes (and anti-registration attributes) is located in the managedpropertyrepository class.
Its main responsibility is to construct a managedproperty object and calculate some of its important attributes, such as globalindex used for Attribute quick hash and typeindex used for Attribute retrieval during compilation.
4. design verification 4.1 Functional requirements Verification
Multiple unit tests have been added for EMPS, and the content of this verification is integrated into item 1. See 5. User Manual.
4.2 WPF binding verification
It is relatively simple to verify. After the application is running Based on it, the values on the interface can be obtained and set properly.
However, we have added a unit test for it, which will be described later.
4.3 Performance Verification
As mentioned earlier, if EMPs is more than 120% of the time consumed than the original property system, the system will be unavailable. According to the previous key point design, it should be achievable. However, it is still necessary to make corresponding verification work and final data.
For details, see the performance test report on Object extended attributes system. The final conclusion is as follows:
"
Performance conclusion:
New OEAHosting a property system not only does not reduce the original performance, but also improves the speed by optimizing useless code. Therefore, you can safely use this attribute system.
"
5 user manual 5.1 use cases (unit test)
Since many unit tests have been added for EMPS, this user manual will mainly introduce unit tests to cover all possible use cases, this section describes how to use each scenario.
The entity classes used by the unit test contain these classes:
The right figure shows all unit tests involved.
"...... The content is too large to be omitted. If you are interested, you can refer to the document in the attachment .................."
5.2 code generation-codesnippets
In the OEA framework demo-product development faster than the prototype, we can see that the Code Generation Technology during compilation is an important part of the OEA Framework's rapid development capability. We have also compiled codesnippets for EMPS 80% use cases (for how to use codesnippets, see: using code snippet in vs to improve development efficiency):
After importing vs, just enter oeap ......, Vs supports the generation of these code snippets, such:
5.3 Other issues 5.3.1 notes for writing CLR attributes of extended attributes
If the attributes defined by EMPs are not extended attributes, a corresponding CLR property package will be defined, for example:
Note: No code can be added to the CLR attribute. All the get and set codes that need to be customized for the code attribute must be written in EMPs as Callback, for example:
The reason is that the interface framework, Orm framework, WPF binding, and other frameworks do not call CLR properties, but directly call the getproperty and setproperty methods. The code in CLR is only for convenience of using class libraries.
5.3.2 when is property extension used and inheritance extension used?
Although EMPs can directly extend attributes of an object type, we still use the old scheme, that is, using the CLR class inheritance mechanism to expand the old entity. Therefore, we need to pay special attention to the differences between the two solutions:
1. Attribute extension refers to the extension of the specified domain entity directly. Once extended, the attributes of the domain entity class in the entire application are extended.
2. Inheritance extensions must be used in different domain entities.
Simply put, when you want to expand a new domain entity class or create a new interface in an application, you can use inheritance extension. In order to fully expand the existing domain entity classes during customization, EMPs should be used for Attribute extension.