Introduction This article takes the actual project as an example to talk about my personal understanding of software development, partial details software project B based on the. NET platform, using the WPF framework, the C # language, the MVVM pattern development of desktop software This software supports visual designer functionality, allowing WYSIWYG ways to add text, images and other elements to the page. The elements can be compiled to parse, generate the corresponding binary data sent to the next machine, this article does not introduce the overall design of software, only to enumerate some of the design and coding details of the independent model layer data type model layer as a separate data access layer, the data type definition remains independent, only record the data itself, UI-independent structures such as Bgproject project types, combining multiple Bgdiargam View objects Bgdiagram view types, combining multiple bgelement element objects, and multiple derived element types when the view layer is working with data Encapsulates the view data type combination model data type to record other UI-related data moderately encapsulated to simplify the code compilation process need to do different processing of text, pictures, etc. only implemented a textcompiler, follow-up implementation of Imagecompiler, Thus extracting the abstract base class Compilerbase form the following structure compile method is implemented by each derived class to implement the compiler logic on the upper level, and it is simple to use polymorphism, as follows
Public BOOLCompile (Bgproject project, outString errormessage) {Textcompiler Textcompiler=NewTextcompiler (project); Imagecompiler Imagecompiler=NewImagecompiler (project); Xxxcompiler Xxxcompiler=NewXxxcompiler (project); foreach(Compilerbase Compilerinch Newcompilerbase[] {textcompiler, Imagecompiler, Xxxcompiler}) {Compiler.compile (); if(!compiler. Validate ( outerrormessage)) { return false; } } // ...}
Don ' t Repeat yourself the compilation logic of each kind of data, you need to traverse the corresponding type of elements, so consider the element traversal logic independent of the base class Travelcompilerbase add the following method
protected static void travelelements<t> (Bgproject project, Bgelementtype ElementType, Action<t> action) where t:bgelement { foreach (bgdiagram diagram in project. Diagrams) { foreach (T element in diagram. Elements.where (E = e.elementtype == ElementType)) { Action (element); } } }
The processing logic is passed in the Textcompiler by the action parameter, invoking the method above, and generating an anonymous method with a lambda expression to complete the processing logic
Travelelements<bgtextelement>(Project, Bgelementtype.text, + = {// .... Deal with the target element accordingly });
To deal with this particular problem, the way in which delegates are used, generics make it easy to use, you can also use templatemethod mode
Appropriately use static types to encapsulate basic tool types static types are a good way to organize independent tools many unprofessional programmers often use static types as containers for storing global objects, which in fact destroys the software structure. You should do everything possible to avoid using static types
variables。
Serialization Tool class
The project involves serializing data to a local file, using the following tool types directly
Public Static classserializeutility { Public Static voidBinarysave<t>(String filePath, T obj) {using(Stream stream =NewFileStream (FilePath, FileMode.Create, FileAccess.Write, Fileshare.none)) {IFormatter Formatter=NewBinaryFormatter (); Formatter. Serialize (stream, obj); } } Public StaticT binaryload<t>(String filePath) {returnBinaryload<t> (FilePath,NULL); } Public StaticT binaryload<t>(String FilePath, Serializationbinder serializationbinder) {if(!file.exists (FilePath)) { return default(T); } using(Stream stream =NewFileStream (FilePath, FileMode.Open, FileAccess.Read, Fileshare.none)) {IFormatter Formatter=NewBinaryFormatter (); if(Serializationbinder! =NULL) {Formatter. Binder=Serializationbinder; } return(T) formatter. Deserialize (stream); } } }
int and byte array conversion tool classes
It involves transferring data to the next computer, considering the data storage format, writing the following tool class, supporting littleending and bigending
//Created by Ant 2014-4-30 Public Static classbytesconverterutility { Public Static byte[] GetBytes (intValueintLengthBOOLIslittleendian =true) { if(Value <0) { Throw NewArgumentException ("value cannot be a negative number"); } if(Length >4) { Throw NewArgumentException ("Lengthcan't >4"); } varRawbytes =bitconverter.getbytes (value); if(Rawbytes.length <length) { Throw NewApplicationException (String.Format ("Bitconverter.getbytes The number of characters {0} returned is less than the target character {1}", Rawbytes.length, Length)); } varbytes =New byte[length]; if(Bitconverter.islittleendian! =Islittleendian) {Array.reverse (rawbytes); Array.copy (rawbytes, Rawbytes.length-length, Bytes,0, length); } Else{array.copy (rawbytes, bytes, length); } returnbytes; } Public Static intToInt (byte[] Bytes,intOffsetintLengthBOOLIslittleendian =true) { if(Length = =1) { returnBytes[offset]; } varTempbytes =New byte[length]; Array.copy (bytes, offset, tempbytes,0, length); if(!Islittleendian) {Array.reverse (tempbytes); } Switch(length) { Case 2: //special handling, converted to unsigned int type, automatically converted to Int32 when returned returnBitconverter.touint16 (Tempbytes,0); Case 4: //Note that this converts the data to a signed int type returnBitconverter.toint32 (Tempbytes,0); default: Throw NewArgumentException ("length non-standard value"); } } }
The convenience of the tool type is its independence, almost no external dependencies, no need to consider the initialization, it can be used directly
[Original] Example-simple design & Thin Code & Reuse Code