西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索
缁崵绮哄銉ュ徔
U婢堆冪瑎v4.7.37.56 閺堚偓閺傛壆澧�U婢堆冪瑎v4.7.37.56 閺堚偓閺傛壆澧�
HD Tune  Prov5.75 濮瑰瀵茬紒鑳閻楃懓鍩嗛悧锟�HD Tune Prov5.75 濮瑰瀵茬紒鑳閻楃懓鍩嗛悧锟�
DiskGenius 娑撴挷绗熼悧鍦�5.2.1.941 鐎规ɑ鏌熼悧锟�DiskGenius 娑撴挷绗熼悧鍦�5.2.1.941 鐎规ɑ鏌熼悧锟�
360鏉烆垯娆㈢粻鈥愁啀v7.5.0.1460 鐎规ɑ鏌熼張鈧弬鎵360鏉烆垯娆㈢粻鈥愁啀v7.5.0.1460 鐎规ɑ鏌熼張鈧弬鎵
Cpu-Z娑擃厽鏋冮悧鍧�1.98.0 缂佽儻澹婃稉顓熸瀮閻楋拷Cpu-Z娑擃厽鏋冮悧鍧�1.98.0 缂佽儻澹婃稉顓熸瀮閻楋拷
缂冩垹绮跺銉ュ徔
閼垫崘顔嗛悽浣冨壋缁犫€愁啀V15.2 鐎规ɑ鏌熷锝呯础閻楋拷閼垫崘顔嗛悽浣冨壋缁犫€愁啀V15.2 鐎规ɑ鏌熷锝呯础閻楋拷
office2016濠碘偓濞茶浼愰崗绌攎sv19.5.2 鐎规ɑ鏌熼張鈧弬鎵office2016濠碘偓濞茶浼愰崗绌攎sv19.5.2 鐎规ɑ鏌熼張鈧弬鎵
鏉╁懘娴�11閺堚偓閺傛壆澧梫11.3.6.1870 鐎规ɑ鏌熼悧锟�鏉╁懘娴�11閺堚偓閺傛壆澧梫11.3.6.1870 鐎规ɑ鏌熼悧锟�
360閸忓秷鍨倃ifi5.3.0.5000 鐎规ɑ鏌熼張鈧弬鎵360閸忓秷鍨倃ifi5.3.0.5000 鐎规ɑ鏌熼張鈧弬鎵
360鐎瑰鍙忓ù蹇氼潔閸o拷2022v13.1.5188.0 鐎规ɑ鏌熷锝呯础閻楋拷360鐎瑰鍙忓ù蹇氼潔閸o拷2022v13.1.5188.0 鐎规ɑ鏌熷锝呯础閻楋拷
婢舵艾鐛熸担鎾惰
闁伴攱鍨滈棅鍏呯閻╋拷2022v9.1.6.2 鐎规ɑ鏌熷锝呯础閻楋拷闁伴攱鍨滈棅鍏呯閻╋拷2022v9.1.6.2 鐎规ɑ鏌熷锝呯础閻楋拷
閺嗘挳顥撹ぐ閬嶇叾2021V5.81.0202.1111鐎规ɑ鏌熷锝呯础閻楋拷閺嗘挳顥撹ぐ閬嶇叾2021V5.81.0202.1111鐎规ɑ鏌熷锝呯础閻楋拷
韫囶偅鎸�5.0濮橀晲绗夐崡鍥╅獓閻楋拷5.0.80 妤犮劌銇旈悧锟�韫囶偅鎸�5.0濮橀晲绗夐崡鍥╅獓閻楋拷5.0.80 妤犮劌銇旈悧锟�
娴兼﹢鍙�2022鐎广垺鍩涚粩鐤�8.0.9.11050 鐎规ɑ鏌熼張鈧弬鎵娴兼﹢鍙�2022鐎广垺鍩涚粩鐤�8.0.9.11050 鐎规ɑ鏌熼張鈧弬鎵
閻栧崬顨岄懝楦款潒妫版叆13.1.5鐎规ɑ鏌熺€瑰宕滈悧锟�閻栧崬顨岄懝楦款潒妫版叆13.1.5鐎规ɑ鏌熺€瑰宕滈悧锟�
閸ユ儳鑸伴崶鎯у剼
photoshop cs6 娑擃厽鏋冮悧锟�13.1.2.3 閸忓秷鍨傛稉顓熸瀮閻楋拷photoshop cs6 娑擃厽鏋冮悧锟�13.1.2.3 閸忓秷鍨傛稉顓熸瀮閻楋拷
Autodesk 3ds Max 2012鐎规ɑ鏌熺粻鈧担鎾茶厬閺傚洨澧梉32&64]Autodesk 3ds Max 2012鐎规ɑ鏌熺粻鈧担鎾茶厬閺傚洨澧梉32&64]
CAD2007閸忓秷鍨傛稉顓熸瀮閻楋拷CAD2007閸忓秷鍨傛稉顓熸瀮閻楋拷
vc鏉╂劘顢戞惔锟�2019閺堚偓閺傛壆澧梫2019.3.2(32&64娴o拷)vc鏉╂劘顢戞惔锟�2019閺堚偓閺傛壆澧梫2019.3.2(32&64娴o拷)
.NET Framework 4.8鐎规ɑ鏌熼悧锟�4.8.3646.NET Framework 4.8鐎规ɑ鏌熼悧锟�4.8.3646
閼卞﹤銇夐懕鏃傜捕
QQ2022v9.5.6.28129 鐎规ɑ鏌熼張鈧弬鎵QQ2022v9.5.6.28129 鐎规ɑ鏌熼張鈧弬鎵
瀵邦喕淇婇悽浣冨壋閻楋拷2022v3.5.0.44 鐎规ɑ鏌熷锝呯础閻楋拷瀵邦喕淇婇悽浣冨壋閻楋拷2022v3.5.0.44 鐎规ɑ鏌熷锝呯础閻楋拷
閸楀啰澧伴崡鏍ь啀瀹搞儰缍旈獮鍐插酱v9.02.02N 鐎规ɑ鏌熼悧锟�閸楀啰澧伴崡鏍ь啀瀹搞儰缍旈獮鍐插酱v9.02.02N 鐎规ɑ鏌熼悧锟�
QT鐠囶參鐓禫4.6.80.18262鐎规ɑ鏌熼張鈧弬鎵QT鐠囶參鐓禫4.6.80.18262鐎规ɑ鏌熼張鈧弬鎵
妞嬬偘淇�2018V6.2.0700 鐎规ɑ鏌熷锝呯础閻楋拷妞嬬偘淇�2018V6.2.0700 鐎规ɑ鏌熷锝呯础閻楋拷
閻㈢喐妞块張宥呭
閺€顖欑帛鐎规繈鎸堕崠锟�(Alipay)V10.2.53.7000 鐎瑰宕滈悧锟�閺€顖欑帛鐎规繈鎸堕崠锟�(Alipay)V10.2.53.7000 鐎瑰宕滈悧锟�
閻ф儳瀹抽崷鏉挎禈鐎佃壈鍩�2022V15.12.10 鐎瑰宕滈幍瀣簚閻楋拷閻ф儳瀹抽崷鏉挎禈鐎佃壈鍩�2022V15.12.10 鐎瑰宕滈幍瀣簚閻楋拷
閹靛婧€濞fê鐤傜€广垺鍩涚粩鐥�10.8.40鐎规ɑ鏌熼張鈧弬鎵閹靛婧€濞fê鐤傜€广垺鍩涚粩鐥�10.8.40鐎规ɑ鏌熼張鈧弬鎵
閻e懘鈧梻缍夐幍瀣簚鐎广垺鍩涚粩鐥�5.6.9 鐎规ɑ鏌熼張鈧弬鎵閻e懘鈧梻缍夐幍瀣簚鐎广垺鍩涚粩鐥�5.6.9 鐎规ɑ鏌熼張鈧弬鎵
閸楀啳浜伴惌銉ㄧ槕閺堝秴濮焌ppv4.5.1鐎规ɑ鏌熼悧锟�閸楀啳浜伴惌銉ㄧ槕閺堝秴濮焌ppv4.5.1鐎规ɑ鏌熼悧锟�
瑜伴亶鐓堕幘顓熸杹
p2psearcher鐎瑰宕滈悧锟�7.3  閹靛婧€閻楋拷p2psearcher鐎瑰宕滈悧锟�7.3 閹靛婧€閻楋拷
闁伴瀚嶉棅鍏呯2022鐎规ɑ鏌熼悧鍦�11.0.8 鐎规ɑ鏌熺€瑰宕滈悧锟�闁伴瀚嶉棅鍏呯2022鐎规ɑ鏌熼悧鍦�11.0.8 鐎规ɑ鏌熺€瑰宕滈悧锟�
閻栧崬顨岄懝鐑樺閺堣櫣澧梫13.1.0閻栧崬顨岄懝鐑樺閺堣櫣澧梫13.1.0
閻ф儳瀹宠ぐ閬嶇叾7.13.0 鐎规ɑ鏌熼張鈧弬鎵閻ф儳瀹宠ぐ閬嶇叾7.13.0 鐎规ɑ鏌熼張鈧弬鎵
瑜伴亶鐓堕崗鍫ユ敱v6.9.0 鐎瑰宕滈幍瀣簚閻楋拷瑜伴亶鐓堕崗鍫ユ敱v6.9.0 鐎瑰宕滈幍瀣簚閻楋拷
闂冨懓顕板銉ュ徔
閼垫崘顔嗛崝銊︽瀬V9.11.5 鐎瑰宕滈悧锟�閼垫崘顔嗛崝銊︽瀬V9.11.5 鐎瑰宕滈悧锟�
娑旓附妫楃亸蹇氼嚛閸忓秷鍨傞悧鍫熸拱v11.5.5.153 鐎规ɑ鏌熼張鈧弬鎵娑旓附妫楃亸蹇氼嚛閸忓秷鍨傞悧鍫熸拱v11.5.5.153 鐎规ɑ鏌熼張鈧弬鎵
QQ闂冨懓顕伴崳鈺漰pV7.7.1.910 鐎规ɑ鏌熼張鈧弬鎵QQ闂冨懓顕伴崳鈺漰pV7.7.1.910 鐎规ɑ鏌熼張鈧弬鎵
閹虫帊姹夐悾鍛儔閸氼兛鍔焌ppv7.1.5 鐎规ɑ鏌熺€瑰宕滈悧锟�閹虫帊姹夐悾鍛儔閸氼兛鍔焌ppv7.1.5 鐎规ɑ鏌熺€瑰宕滈悧锟�
鐠ч鍋g拠璁冲姛app閺傛壆澧楅張锟�20227.9.186 鐎瑰宕滈悧锟�鐠ч鍋g拠璁冲姛app閺傛壆澧楅張锟�20227.9.186 鐎瑰宕滈悧锟�
闁叉垼鐎洪悶鍡氬偍
楠炲啿鐣ㄧ拠浣稿煖鐎瑰…閻炲棜鍌╒9.1.0.1 鐎规ɑ鏌熺€瑰宕滈悧锟�楠炲啿鐣ㄧ拠浣稿煖鐎瑰…閻炲棜鍌╒9.1.0.1 鐎规ɑ鏌熺€瑰宕滈悧锟�
濞寸兘鈧俺鐦夐崚鍛婂閺堣櫣澧�(e濞寸兘鈧俺鍌�)8.71 鐎规ɑ鏌熺€瑰宕滈悧锟�濞寸兘鈧俺鐦夐崚鍛婂閺堣櫣澧�(e濞寸兘鈧俺鍌�)8.71 鐎规ɑ鏌熺€瑰宕滈悧锟�
娑撴粍鎹g拠浣稿煖娑撴粍鎹i悶鍡氬偍4.0.5 鐎瑰宕滈悧锟�娑撴粍鎹g拠浣稿煖娑撴粍鎹i悶鍡氬偍4.0.5 鐎瑰宕滈悧锟�
娑擃參鎽辩拠浣稿煖缁夎濮╅悶鍡氬偍鏉烆垯娆�6.02.010 鐎规ɑ鏌熺€瑰宕滈悧锟�娑擃參鎽辩拠浣稿煖缁夎濮╅悶鍡氬偍鏉烆垯娆�6.02.010 鐎规ɑ鏌熺€瑰宕滈悧锟�
閸楀酣绶崇拠浣稿煖鐏忓繘鍣鹃幍瀣簚閻炲棜鍌ㄦ潪顖欐3.2.4 鐎瑰宕滈悧锟�閸楀酣绶崇拠浣稿煖鐏忓繘鍣鹃幍瀣簚閻炲棜鍌ㄦ潪顖欐3.2.4 鐎瑰宕滈悧锟�
閹靛婧€闁炬儼顢�
缁傚繐缂撻崘婊勬綑娣囷紕鏁ょ粈鐐閺堟椽鎽辩悰灞筋吂閹撮顏�2.3.4 鐎瑰宕滈悧锟�缁傚繐缂撻崘婊勬綑娣囷紕鏁ょ粈鐐閺堟椽鎽辩悰灞筋吂閹撮顏�2.3.4 鐎瑰宕滈悧锟�
閺勬挸鍩楁担婊嗩潒妫版垵澹€鏉堟叧pp4.1.16鐎瑰宕滈悧锟�閺勬挸鍩楁担婊嗩潒妫版垵澹€鏉堟叧pp4.1.16鐎瑰宕滈悧锟�
閺€顖欑帛鐎规繈鎸堕崠锟�(Alipay)V10.2.53.7000 鐎瑰宕滈悧锟�閺€顖欑帛鐎规繈鎸堕崠锟�(Alipay)V10.2.53.7000 鐎瑰宕滈悧锟�
娑擃厼娴楀銉ユ櫌闁炬儼顢戦幍瀣簚闁炬儼顢慳ppV7.0.1.2.5 鐎瑰宕滈悧锟�娑擃厼娴楀銉ユ櫌闁炬儼顢戦幍瀣簚闁炬儼顢慳ppV7.0.1.2.5 鐎瑰宕滈悧锟�
娑擃厼娴楅柧鎯邦攽閹靛婧€闁炬儼顢戠€广垺鍩涚粩锟�7.2.5 鐎规ɑ鏌熺€瑰宕滈悧锟�娑擃厼娴楅柧鎯邦攽閹靛婧€闁炬儼顢戠€广垺鍩涚粩锟�7.2.5 鐎规ɑ鏌熺€瑰宕滈悧锟�
娴兼垿妫介惄濠冩
閼垫崘顔嗛悮搴ㄥ鏉堝彞姹夐幍瀣簚閻楀湸2.3.0.0 鐎规ɑ鏌熺€瑰宕滈悧锟�閼垫崘顔嗛悮搴ㄥ鏉堝彞姹夐幍瀣簚閻楀湸2.3.0.0 鐎规ɑ鏌熺€瑰宕滈悧锟�
閸旇尪鍨堕崶銏犵暭閺傝顒滈悧鍫熷濞撶1.2.1鐎规ɑ鏌熼悧锟�閸旇尪鍨堕崶銏犵暭閺傝顒滈悧鍫熷濞撶1.2.1鐎规ɑ鏌熼悧锟�
妤椼儵銈挎ご銊╁鏉╂稑瀵查弮鐘绘闁借崵鐓堕悧鍧�7.8.0.0鐎瑰宕滈悧锟�妤椼儵銈挎ご銊╁鏉╂稑瀵查弮鐘绘闁借崵鐓堕悧鍧�7.8.0.0鐎瑰宕滈悧锟�
濡炲秶澧挎径褎鍨崓闈涙閸忋劍妲戦弰锟�1.0.91 鐎瑰宕滈悧锟�濡炲秶澧挎径褎鍨崓闈涙閸忋劍妲戦弰锟�1.0.91 鐎瑰宕滈悧锟�
閸斻劋缍旂亸鍕毊
閸﹂绗呴崺搴g崐閸戞槒鈧崑t閻楋拷1.6.3 鐎规ɑ鏌熼悧锟�閸﹂绗呴崺搴g崐閸戞槒鈧崑t閻楋拷1.6.3 鐎规ɑ鏌熼悧锟�
鐟佸懐鏁抽懕鏃傛礃1.325.157 鐎瑰宕滈悧锟�鐟佸懐鏁抽懕鏃傛礃1.325.157 鐎瑰宕滈悧锟�
閸︼絾鏋熸竟顐fЕ閻垽娉︾紒鎼�4.2.1 鐎瑰宕滈悧锟�閸︼絾鏋熸竟顐fЕ閻垽娉︾紒鎼�4.2.1 鐎瑰宕滈悧锟�
闁喖銇�3D閹靛鐖�1.0.9鐎瑰宕滈悧锟�闁喖銇�3D閹靛鐖�1.0.9鐎瑰宕滈悧锟�
婵夋棃妲诲〒鍛婂灆
鐎瑰宕滃宥囧⒖婢堆勫灛閸嶉潧妗�2姒涙垶娈弮鏈靛敩娣囶喗鏁奸悧鍦�1.9.5 閺堚偓閺傛壆澧�鐎瑰宕滃宥囧⒖婢堆勫灛閸嶉潧妗�2姒涙垶娈弮鏈靛敩娣囶喗鏁奸悧鍦�1.9.5 閺堚偓閺傛壆澧�
娑旇鲸鏋熺憲鎸庣埗2v1.0.150鐎瑰宕滈悧锟�娑旇鲸鏋熺憲鎸庣埗2v1.0.150鐎瑰宕滈悧锟�
娣囨繂宕奸拃婵嗗椽3閺冪娀妾洪柦鑽ょ叾閺堚偓閺傛壆澧梫2.0.0.1 鐎瑰宕滈悧锟�娣囨繂宕奸拃婵嗗椽3閺冪娀妾洪柦鑽ょ叾閺堚偓閺傛壆澧梫2.0.0.1 鐎瑰宕滈悧锟�
閸欙綀顣伴懟閬嶆碂閸楁洘婧€閻楋拷1.2.0 鐎瑰宕滈悧锟�閸欙綀顣伴懟閬嶆碂閸楁洘婧€閻楋拷1.2.0 鐎瑰宕滈悧锟�
鐏忓繐鐨崘娑樻礋鐎瑰宕滈悧锟�2.7.4 閺冪娀妾洪柌鎴濈娣囶喗鏁奸悧锟�鐏忓繐鐨崘娑樻礋鐎瑰宕滈悧锟�2.7.4 閺冪娀妾洪柌鎴濈娣囶喗鏁奸悧锟�
鐠ф稖婧呯粩鐐村Η
閻ц鍖楃挧娑滄簠2閹靛鐖�1.47.1  鐎瑰宕滈悧锟�閻ц鍖楃挧娑滄簠2閹靛鐖�1.47.1 鐎瑰宕滈悧锟�
娑撯偓鐠ч攱娼垫鐐舵簠鐎瑰宕滈悧鍧�2.9.14 閺堚偓閺傛壆澧�娑撯偓鐠ч攱娼垫鐐舵簠鐎瑰宕滈悧鍧�2.9.14 閺堚偓閺傛壆澧�
鐠烘垼绐囬崡鈥茬鏉烇附澧滈張铏瑰鐎规ɑ鏌熼張鈧弬鎵v1.16.2 鐎瑰宕滈悧锟�鐠烘垼绐囬崡鈥茬鏉烇附澧滈張铏瑰鐎规ɑ鏌熼張鈧弬鎵v1.16.2 鐎瑰宕滈悧锟�
閻欏倿鍣规娆掓簠8閺嬩線鈧喎鍣锋禍鎴滄叏閺€鍦(閸忓秵鏆熼幑顔煎瘶)v4.6.0j 闁叉垵绔甸弮鐘绘閻楋拷閻欏倿鍣规娆掓簠8閺嬩線鈧喎鍣锋禍鎴滄叏閺€鍦(閸忓秵鏆熼幑顔煎瘶)v4.6.0j 闁叉垵绔甸弮鐘绘閻楋拷
閻у彞绠伴崡鍐仏閹规洟濂�2021閺堚偓閺傛壆澧�5.78 鐎瑰宕滈悧锟�閻у彞绠伴崡鍐仏閹规洟濂�2021閺堚偓閺傛壆澧�5.78 鐎瑰宕滈悧锟�
鐟欐帟澹婇幍顔界川
濮婏箑澶熼崜鎴e灦閼板懎褰夐幀浣哄1.0.1.2鐎瑰宕滈悧锟�濮婏箑澶熼崜鎴e灦閼板懎褰夐幀浣哄1.0.1.2鐎瑰宕滈悧锟�
娴犳瑥顣ㄦ导鐘侯嚛ro婢跺秴鍙寸€瑰宕滈悧锟�1.20.3閺堚偓閺傛壆澧�娴犳瑥顣ㄦ导鐘侯嚛ro婢跺秴鍙寸€瑰宕滈悧锟�1.20.3閺堚偓閺傛壆澧�
濮婏箑澶熺拠娑楃舶閹靛鐖堕悧锟�1.3.6 鐎规ɑ鏌熺€瑰宕滈悧锟�濮婏箑澶熺拠娑楃舶閹靛鐖堕悧锟�1.3.6 鐎规ɑ鏌熺€瑰宕滈悧锟�
閻滃鈧懓宕抽懓鈧琕3.72.1.1 鐎瑰宕滈張鈧弬鏉跨暭閺傚湱澧�閻滃鈧懓宕抽懓鈧琕3.72.1.1 鐎瑰宕滈張鈧弬鏉跨暭閺傚湱澧�
鐠嬩礁顔嶇亸蹇氭簠瀵儤澧滈張铏瑰v1.0.49 鐎瑰宕滈悧锟�鐠嬩礁顔嶇亸蹇氭簠瀵儤澧滈張铏瑰v1.0.49 鐎瑰宕滈悧锟�
缁崵绮烘潪顖欐
mac绾句胶娲忛崚鍡楀隘瀹搞儱鍙�(Paragon Camptune X)V10.8.12鐎规ɑ鏌熼張鈧弬鎵mac绾句胶娲忛崚鍡楀隘瀹搞儱鍙�(Paragon Camptune X)V10.8.12鐎规ɑ鏌熼張鈧弬鎵
閼昏鐏夐幙宥勭稊缁崵绮篗ACOSX 10.9.4 Mavericks鐎瑰苯鍙忛崗宥堝瀭閻楋拷閼昏鐏夐幙宥勭稊缁崵绮篗ACOSX 10.9.4 Mavericks鐎瑰苯鍙忛崗宥堝瀭閻楋拷
Rar鐟欙絽甯囬崚鈺佹珤mac閻楀澊1.4 鐎规ɑ鏌熼崗宥堝瀭閻楋拷Rar鐟欙絽甯囬崚鈺佹珤mac閻楀澊1.4 鐎规ɑ鏌熼崗宥堝瀭閻楋拷
Mac鐎瑰宕滃Ο鈩冨珯閸o拷(ARC Welder)v1.0 鐎规ɑ鏌熼張鈧弬鎵Mac鐎瑰宕滃Ο鈩冨珯閸o拷(ARC Welder)v1.0 鐎规ɑ鏌熼張鈧弬鎵
Charles for MacV3.9.3鐎规ɑ鏌熼悧锟�Charles for MacV3.9.3鐎规ɑ鏌熼悧锟�
缂冩垹绮跺銉ュ徔
閹兼粎瀚嶅ù蹇氼潔閸b暕ac閻楀澊5.2 鐎规ɑ鏌熷锝呯础閻楋拷閹兼粎瀚嶅ù蹇氼潔閸b暕ac閻楀澊5.2 鐎规ɑ鏌熷锝呯础閻楋拷
闁挎劖宓庣€广垺鍩涚粩鐥琣c閻楀湸1.33鐎规ɑ鏌熼張鈧弬鎵闁挎劖宓庣€广垺鍩涚粩鐥琣c閻楀湸1.33鐎规ɑ鏌熼張鈧弬鎵
韫囶偆澧甿ac閻楀澊1.3.2 鐎规ɑ鏌熷锝呯础閻楋拷韫囶偆澧甿ac閻楀澊1.3.2 鐎规ɑ鏌熷锝呯础閻楋拷
閺嬩胶鍋f禍鏃傜應Mac閻楋拷7.13濮濓絽绱¢悧锟�閺嬩胶鍋f禍鏃傜應Mac閻楋拷7.13濮濓絽绱¢悧锟�
婵帊缍嬪銉ュ徔
Apple Logic Pro xV10.3.2Apple Logic Pro xV10.3.2
Adobe Premiere Pro CC 2017 mac閻楀澊11.0.0 娑擃厽鏋冮悧锟�Adobe Premiere Pro CC 2017 mac閻楀澊11.0.0 娑擃厽鏋冮悧锟�
閸楀啫宕堥棃娆忔儔Mac閻楀湸9.1.1 鐎规ɑ鏌熼張鈧弬鎵閸楀啫宕堥棃娆忔儔Mac閻楀湸9.1.1 鐎规ɑ鏌熼張鈧弬鎵
Mac缂冩垹绮堕惄瀛樻尡鏉烆垯娆�(MacTV)v0.121 鐎规ɑ鏌熼張鈧弬鎵Mac缂冩垹绮堕惄瀛樻尡鏉烆垯娆�(MacTV)v0.121 鐎规ɑ鏌熼張鈧弬鎵
Adobe Fireworks CS6 Mac閻楀湑S6鐎规ɑ鏌熺粻鈧担鎾茶厬閺傚洨澧�Adobe Fireworks CS6 Mac閻楀湑S6鐎规ɑ鏌熺粻鈧担鎾茶厬閺傚洨澧�
閸ユ儳鑸伴崶鎯у剼
AutoCAD2015 mac娑擃厽鏋冮悧鍫熸拱v1.0 鐎规ɑ鏌熷锝呯础閻楋拷AutoCAD2015 mac娑擃厽鏋冮悧鍫熸拱v1.0 鐎规ɑ鏌熷锝呯础閻楋拷
Adobe Photoshop cs6 mac閻楀澊13.0.3 鐎规ɑ鏌熸稉顓熸瀮閻楋拷Adobe Photoshop cs6 mac閻楀澊13.0.3 鐎规ɑ鏌熸稉顓熸瀮閻楋拷
Mac閻垽鍣虹紒妯烘禈鏉烆垯娆�(Sketch mac)v3.3.2 娑擃厽鏋冮悧锟�Mac閻垽鍣虹紒妯烘禈鏉烆垯娆�(Sketch mac)v3.3.2 娑擃厽鏋冮悧锟�
Adobe After Effects cs6 mac閻楀澊1.0娑擃厽鏋冮悧锟�Adobe After Effects cs6 mac閻楀澊1.0娑擃厽鏋冮悧锟�
Adobe InDesign cs6 mac1.0 鐎规ɑ鏌熸稉顓熸瀮閻楋拷Adobe InDesign cs6 mac1.0 鐎规ɑ鏌熸稉顓熸瀮閻楋拷
鎼存梻鏁ゆ潪顖欐
Mac閻楀牆鎻╅幘锟�1.1.26 鐎规ɑ鏌熷锝呯础閻楀溂dmg]Mac閻楀牆鎻╅幘锟�1.1.26 鐎规ɑ鏌熷锝呯础閻楀溂dmg]
Mac鐠囪鍟揘TFS(Paragon NTFS for Mac)12.1.62 鐎规ɑ鏌熷锝呯础閻楋拷Mac鐠囪鍟揘TFS(Paragon NTFS for Mac)12.1.62 鐎规ɑ鏌熷锝呯础閻楋拷
鏉╁懘娴�10 for macv3.4.1.4368 鐎规ɑ鏌熼張鈧弬鎵鏉╁懘娴�10 for macv3.4.1.4368 鐎规ɑ鏌熼張鈧弬鎵
Mac娑撳娓跺鍝勩亣閻ㄥ嫮閮寸紒鐔哥閻炲棗浼愰崗锟�(CleanMyMac for mac)v3.1.1 濮濓絽绱¢悧锟�Mac娑撳娓跺鍝勩亣閻ㄥ嫮閮寸紒鐔哥閻炲棗浼愰崗锟�(CleanMyMac for mac)v3.1.1 濮濓絽绱¢悧锟�
閼昏鐏塀ootCamp5.1.5640 鐎规ɑ鏌熼張鈧弬鎵閼昏鐏塀ootCamp5.1.5640 鐎规ɑ鏌熼張鈧弬鎵
ios缁€鍙ユ唉閼卞﹤銇�
瀵邦喕淇奿pad閻楋拷2020v7.0.12 鐎规ɑ鏌熼悧锟�瀵邦喕淇奿pad閻楋拷2020v7.0.12 鐎规ɑ鏌熼悧锟�
iphone閹靛婧€qq2021v8.5.0 鐎规ɑ鏌熼悧锟�iphone閹靛婧€qq2021v8.5.0 鐎规ɑ鏌熼悧锟�
閺勬挷淇奿OS閻楀澊7.3.13 iPhone閻楋拷閺勬挷淇奿OS閻楀澊7.3.13 iPhone閻楋拷
闂勫矂妾� iphoneV8.32.4 鐎规ɑ鏌熷锝呯础閻楋拷闂勫矂妾� iphoneV8.32.4 鐎规ɑ鏌熷锝呯础閻楋拷
閸楀啰澧� iphone閻楋拷9.2.5 鐎规ɑ鏌熼悧锟�閸楀啰澧� iphone閻楋拷9.2.5 鐎规ɑ鏌熼悧锟�
ios閻㈢喐妞块張宥呭
99娑撱儵鈧娓堕弬鎵V1.3.699娑撱儵鈧娓堕弬鎵V1.3.6
韫囶偆澧甶Phone閻楋拷5.7.3 鐎规ɑ鏌熼悧锟�韫囶偆澧甶Phone閻楋拷5.7.3 鐎规ɑ鏌熼悧锟�
濞fê鐤� for iPhonev9.5.15 鐎规ɑ鏌熼張鈧弬鎵濞fê鐤� for iPhonev9.5.15 鐎规ɑ鏌熼張鈧弬鎵
婢с劏鎶楁径鈺傜毜 for iphoneV7.5.3鐎规ɑ鏌熼張鈧弬鎵IPA婢с劏鎶楁径鈺傜毜 for iphoneV7.5.3鐎规ɑ鏌熼張鈧弬鎵IPA
鐠嬮攱鐡曢崷鏉挎禈iphone(Google Maps)4.54  娑擃厽鏋冮悧锟�鐠嬮攱鐡曢崷鏉挎禈iphone(Google Maps)4.54 娑擃厽鏋冮悧锟�
ios瑜伴亶鐓舵繛鍙樼
韫囶偅鎸遍懟瑙勭亯閻楀湸3.3.35 鐎规ɑ鏌熼悧鍦糹pa]韫囶偅鎸遍懟瑙勭亯閻楀湸3.3.35 鐎规ɑ鏌熼悧鍦糹pa]
閸氬鎮忚ぐ閬嶇叾閹绢厽鏂侀崳鈺s閻楋拷1.0.1017 閼昏鐏塱pad閻楋拷閸氬鎮忚ぐ閬嶇叾閹绢厽鏂侀崳鈺s閻楋拷1.0.1017 閼昏鐏塱pad閻楋拷
瑜伴亶鐓堕崗鍫ユ敱閹绢厽鏂侀崳鈺s閻楋拷2.8.0 鐎规ɑ鏌熼悧锟�瑜伴亶鐓堕崗鍫ユ敱閹绢厽鏂侀崳鈺s閻楋拷2.8.0 鐎规ɑ鏌熼悧锟�
閺傛濂旈惄瀛樻尡鐎广垺鍩涚粩鐥爋s閻楋拷7.0.1 鐎规ɑ鏌熼張鈧弬鎵閺傛濂旈惄瀛樻尡鐎广垺鍩涚粩鐥爋s閻楋拷7.0.1 鐎规ɑ鏌熼張鈧弬鎵
闁伴瀚嶉棅鍏呯 for iPhonev10.9.0 鐎规ɑ鏌熼張鈧弬鎵闁伴瀚嶉棅鍏呯 for iPhonev10.9.0 鐎规ɑ鏌熼張鈧弬鎵
ios閸ユ儳鑸伴崶鎯у剼
How old do I look ios閻楋拷1.02 鐎规ɑ鏌熼悧锟�How old do I look ios閻楋拷1.02 鐎规ɑ鏌熼悧锟�
缂囧骸娴樼粔鈧粔鈧琲Phone閻楀湸8.6.62 閺堚偓閺傜増顒滃蹇曞缂囧骸娴樼粔鈧粔鈧琲Phone閻楀湸8.6.62 閺堚偓閺傜増顒滃蹇曞
濮樻潙宓冮梼鐔兼毐閼昏鐏夐悧鍧�1.0.0濮樻潙宓冮梼鐔兼毐閼昏鐏夐悧鍧�1.0.0
婢垛晛銇塸閸ョ穭pad閻楋拷5.7.4 鐎规ɑ鏌熼悧锟�婢垛晛銇塸閸ョ穭pad閻楋拷5.7.4 鐎规ɑ鏌熼悧锟�
韫囶偅澧渋os閻楀湸9.6.30 鐎规ɑ鏌熼悧锟�韫囶偅澧渋os閻楀湸9.6.30 鐎规ɑ鏌熼悧锟�
ios濞村繗顫嶅銉ュ徔
閼冲苯瀵橀崷鏉挎禈ios閻楋拷1.0 鐎规ɑ鏌熼張鈧弬鎵閼冲苯瀵橀崷鏉挎禈ios閻楋拷1.0 鐎规ɑ鏌熼張鈧弬鎵
閹靛婧€鐎瑰鍙忛崝鈺傚閼昏鐏夐悧鍧�1.0 鐎规ɑ鏌熼張鈧弬鎵閹靛婧€鐎瑰鍙忛崝鈺傚閼昏鐏夐悧鍧�1.0 鐎规ɑ鏌熼張鈧弬鎵
UC濞村繗顫嶉崳鈺�113.5.5.1555娑擃厽鏋冮悧锟�UC濞村繗顫嶉崳鈺�113.5.5.1555娑擃厽鏋冮悧锟�
360濞村繗顫嶉崳鈩塂 for iPadV4.1.3  濮濓絽绱¢悧锟�360濞村繗顫嶉崳鈩塂 for iPadV4.1.3 濮濓絽绱¢悧锟�
iPhone閹靛婧€QQ濞村繗顫嶉崳鈺�8.9.1 鐎规ɑ鏌熼悧锟�iPhone閹靛婧€QQ濞村繗顫嶉崳鈺�8.9.1 鐎规ɑ鏌熼悧锟�

首页编程开发C#.NET → 关于用C#实现B/S与C/S平台之间功能通用性的设计思路

关于用C#实现B/S与C/S平台之间功能通用性的设计思路

相关文章发表评论 来源:liping13599168时间:2010/3/1 17:28:40字体大小:A-A+

作者:admin点击:1172次评论:0次标签: C/S

  • 类型:备份还原大小:46.7M语言:英文 评分:6.6
  • 标签:
立即下载

设计场景

1. 有A,B两组开发人员进行某个系统的开发,其中A组开发人员负责B/S平台的功能设计与开发,B组开发人员负责C/S平台的功能设计与开发。

2. 在当时的项目背景下,B/S端的项目是先启动的,而A组的开发人员还没有意识到将来需要配合C/S端来做功能协作,因此产生的问题就是,前期的系统架构设计没有过多地考虑以适应多个平台下的功能适应性。当然,从B/S端的设计角度上看,系统架构还算比较清晰。接着A组的开发人员就在这样的情况下,完成了系统功能的实现。

3. 接着高层领导告诉项目经理需要做一套C/S架构的软件来配合B/S端平台的使用,而这时候B/S端的功能实现已经基本完成,B组开发人员成立。

4. 在B组架构人员开始设计架构的时候,并没有衍用B/S端的开发架构,很多基础架构(如分层模式、数据库结构、数据实体类等等)都存在很大的差异(C/S端项目在初期的要求没有那么高,有的功能能削减掉就削减掉),后来B组架构人员发现需求文档上的有个功能和B/S平台上的某个功能是一样的,于是他和A组架构人员进行交流,希望负责B/S平台上这个功能的开发人员能够帮助C/S平台帮助完成这一功能。于是A组的Leepy就匆匆忙忙地上阵了。

5. 最初Leepy同学因为在B/S平台上也有大量的任务需要完成,任务赶得狠,又收到这样一个“功能复制”的任务,心想:“那么就先把功能复制一份上去,然后如果B/S平台上的功能有更新,就同步修改C/S平台就好”。于是打开C/S平台的项目,发现和B/S平台项目的差异性比较大,包括数据库结构和数据实体类等等,更头疼的是这里采用的是.net framework 2.0进行开发,而B/S端采用的是.net framework 3.5进行开发,而且从功能上,Leepy使用大量的3.5的属性。要直接复用是不可能的,还需要调整相应的代码。

6. 于是C/S平台该功能出来了,运行得还行。现在才是郁闷的开始,因为该功能属于平台的核心模块,于是B/S平台上要时刻调整得比较大,所以同步的C/S端的功能也要相应的调整,然后又运行完好。于是问题出来了,这样反复地修改导致系统(C/S和B/S)维护成本很高,架构间的设计耦合度太大。刚开始Leepy抱怨为什么C/S端没有和B/S端统一架构,至少底层基础平台能够设计得具有可扩展性,光光抱怨无法解决问题,因为这是项目的人员配置的问题。于是,Leepy想到了必须对该功能进重构,使用一个通用的组件进行抽象,而实际实现的,如C/S、B/S端具体应用,只要维护相应的业务代码。

 

设计思路

1. 说完场景,现在说说动手的部分。以一个中学生教育平台591up的网站为例,以及教育平台客户端的辅助软件。

这一功能实现一份Word文档试卷的导入保存并分解文档中的试题,将试题逐个保存入库(解析出来的试题部分还包括很多属性,如答案、知识点、解题关键点等很多属性)。现在B/S平台和C/S平台都需要这个功能,但是B/S平台和C/S平台下的相关数据库实体类,设计不很统一,导致维护系统的成本很高。于是,考虑是否能将解析器的设计与业务功能分开,将试卷解析器设计成通用的组件,而与B/S端和C/S端的业务代码彻底分开,对于解析的逻辑代码(基础代码)在两端都可以引用到,而B/S端和C/S端所需要做得就是调整业务代码,并不需要关解析的基础代码是什么,组件与业务代码解耦。如下图所示:

 

2. 现在讲讲具体设计思路,先从试卷解析器基础组件开始(为了简化,该范例是削弱版的),创建一个.net 2.0的类库(为了适应客户端.net 2.0的配置)声明一个试卷解析器范型接口:

代码
/// <summary>
/// 试卷转换器泛型接口
/// </summary>
public interface IPaperConvertor<TIn, TOut>
{
/// <summary>
/// 转换方法
/// </summary>
/// <param name="tIn">转换输入类型</param>
/// <param name="helper">Word处理接口</param>
/// <returns>转换输出类型</returns>
TOut Convert(TIn tIn, IWordHelper helper);
}
其中TIn类型作为输入类型,TOut类型作为输出类型(TIn将来作为业务代码中实际的输入类型,如WordInfo类;TOut作为实际输出类型,如PaperInfo类;IWordHelper为一个Word处理接口,这里的实现是Microsoft.Office.Interop.Word)

考虑到转换器在转换过程Convert中,会产生一系列的步骤,首先对于转换这个过程进行细化,分解成各个步骤:

代码
public abstract class BasePaperConvertor<TIn, TOut> : IPaperConvertor<TIn, TOut>
where TIn : class, new()
where TOut : class, new()
{
//成员

/// <summary>
/// 输出试卷实体
/// </summary>
protected TOut Paper { get; set; }

/// <summary>
/// 输入Word条件
/// </summary>
protected TIn WordInfo { get; set; }

#region Word操作实体属性
/// <summary>
/// Word操作实体属性
/// </summary>
protected IWordHelper WordHelper { get; set; }
#endregion

//公共方法

/// <summary>
/// 转换方法
/// </summary>
/// <param name="tIn"></param>
/// <returns></returns>
public virtual TOut Convert(TIn tIn, IWordHelper helper)
{
WordHelper = helper;
WordInfo = tIn;
Paper = Initialize(tIn);

if (Prepare())
Execute();

Finished();

return Paper;
}

//抽象方法

/// <summary>
/// 初始化
/// </summary>
/// <param name="tIn"></param>
/// <returns></returns>
protected abstract TOut Initialize(TIn tIn);

/// <summary>
/// 预装载
/// </summary>
/// <param name="tOut"></param>
/// <returns></returns>
protected abstract bool Prepare();

/// <summary>
/// 执行
/// </summary>
/// <param name="tOut"></param>
protected abstract void Execute();

/// <summary>
/// 完成
/// </summary>
protected abstract void Finished();
}
从代码中,我们可以看到Convert方法中调用了一系列的抽象方法,首先对于输入类型进行初始化(Initialize),接着通过输入类型预装载(Prepare),如果预装载成功,并开始执行。最后完成(Finished)所有的工作。

接着,需要定义一个包含Word解析逻辑代码的抽象类,这里使用Microsoft.Office.Interop.Word进行Office编程,于是创建名为

OfficeWordPaperConvertor.cs的类:

OfficeWordPaperConvertor
/// <summary>
/// 试卷解析器泛型抽象类
/// </summary>
public abstract class OfficeWordPaperConvertor<TIn, TQuestion, TOut> : BasePaperConvertor<TIn, TOut>
where TIn : class, new()
where TQuestion : class, new()
where TOut : class, new()
{

#region 试卷Word结构信息
/// <summary>
/// 试卷Word结构信息
/// </summary>
protected PaperWordInfo PaperWordInfo { get; private set; }
#endregion

#region Word操作辅助类属性
private OfficeWordHelper _OfficeWordHelper;
/// <summary>
/// Word操作辅助类属性
/// </summary>
protected OfficeWordHelper OfficeWordHelper
{
get
{
if (_OfficeWordHelper == null)
_OfficeWordHelper = GetWordHelper();
return _OfficeWordHelper;
}
}
#endregion

#region 预处理试卷
/// <summary>
/// 预处理试卷
/// </summary>
/// <param name="tOut"></param>
/// <returns></returns>
protected override bool Prepare()
{
//过滤试卷无效信息
FilterPaper();

//解析试卷
ParsePaper();

return true;
}
#endregion

#region 执行试卷
/// <summary>
/// 执行试卷
/// </summary>
/// <param name="tOut"></param>
protected override void Execute()
{
for (int i = 0; i < PaperWordInfo.Count; i++)
{
QuestionWordInfo questionWordInfo = PaperWordInfo[i];

//执行试题
ExcuteQuestion(questionWordInfo);
}
}
#endregion

#region 完成时调用
/// <summary>
/// 完成时调用
/// </summary>
protected override void Finished()
{
//这里进行完成时调用的实现

//..
}
#endregion

//虚方法

/// <summary>
/// 过滤试卷无效信息
/// </summary>
protected virtual void FilterPaper()
{

}

/// <summary>
/// 解析试卷
/// </summary>
protected virtual void ParsePaper()
{
PaperWordInfo = new PaperWordInfo();

//通过计算 OfficeWordHelper.Document.Text 得到文本中的题目数,这里省去这段逻辑
PaperWordInfo.AddQuestion(new QuestionWordInfo { StartIndex = 0, EndIndex = 0 });
PaperWordInfo.AddQuestion(new QuestionWordInfo { StartIndex = 1, EndIndex = 1 });
PaperWordInfo.AddQuestion(new QuestionWordInfo { StartIndex = 2, EndIndex = 2 });
}

/// <summary>
/// 执行试题
/// </summary>
/// <param name="questionWordInfo"></param>
protected virtual void ExcuteQuestion(QuestionWordInfo questionWordInfo)
{
string[] array = OfficeWordHelper.Document.Text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

//创建试题解析器实体
TQuestion question = CreateQuestionConvertor(WordInfo, array[questionWordInfo.StartIndex]);

//将试题添加到试卷中
if (question != null) AddQuestion(question);
}

#region 获取Word工具类
/// <summary>
/// 获取Word工具类
/// </summary>
/// <returns></returns>
protected OfficeWordHelper GetWordHelper()
{
return WordHelper as OfficeWordHelper;
}
#endregion

//抽象方法

/// <summary>
/// 创建试题解析器实体
/// </summary>
/// <param name="subject"></param>
protected abstract TQuestion CreateQuestionConvertor(TIn tIn, string wordContent);

/// <summary>
/// 将试题添加到试卷中
/// </summary>
/// <param name="tPart"></param>
/// <param name="tQuestion"></param>
protected abstract void AddQuestion(TQuestion tQuestion);
}
为何这里没有重写Initialize方法呢?由于这里需要将Initialize暴露于业务代码中,可以通过业务代码来重写该方法,如果业务组件没有调用Initialize,将报错。

这里Prepare方法主要完成一份Word文档的信息过滤,并且将文档中按照试题题号进行拆分试题,形成试题列表。

Execute方法完成一份试卷的执行,通过试题列表将题目逐题入库。

Finshed方法在Execute之后,可通过事件委托告诉用户解析已经完成。

在后面附加的例子中,我会引用OfficeWordHelper.Document.Text 等于“1.试题1\r\n2.试题2\r\n3.试题3”的文本字符串来模拟Word文档中的文字(实际情况更

加复杂,Word文档中包括图片,符号,OLE对象等等,一切为了简化说明,这里省略该步骤),说明它拆分出来的试题有3道。QuestionWordInfo 类的

StartIndex,EndIndex对应试题所在行数索引。

接着注意ExcuteQuestion这个方法,调用了CreateQuestionConvertor和AddQuestion两个抽象方法。该两个抽象方法将在业务组件中实现。

 

试卷解析器基本设计实现了,现在看下试题解析器该如何实现:

声明一个试题解析器范型接口:

/// <summary>
/// 试题转换器泛型接口
/// </summary>
public interface IQuestionConvertor<TIn, TOut>
{
TOut Convert(TIn tIn, string wordContent);
}
其中TIn类型作为输入类型,TOut类型作为输出类型(TIn将来作为业务代码中实际的输入类型,如WordInfo类;TOut作为实际输出类型,如QuestionInfo类)

考虑到转换器在转换过程Convert中,会产生一系列的步骤,首先对于转换这个过程进行细化,分解成各个步骤:

代码
public abstract class BaseQuestionConvertor<TIn, TOut> : IQuestionConvertor<TIn, TOut> where TIn : class, new()
{
//成员

#region 输出试卷属性
/// <summary>
/// 输出试卷实体
/// </summary>
protected TOut Question { get; set; }
#endregion
#region 输入Word实体属性
/// <summary>
/// 输入Word实体属性
/// </summary>
protected TIn WordInfo { get; set; }
#endregion

//公共方法

#region 转换方法
/// <summary>
/// 转换方法
/// </summary>
/// <param name="tIn"></param>
/// <param name="helper"></param>
/// <returns></returns>
public virtual TOut Convert(TIn tIn, string wordContent)
{
WordInfo = tIn;
Question = Initialize(tIn);

//解析试题
TOut tOut = Execute(wordContent);

//完成
Finished();

return tOut;
}
#endregion

//抽象方法

#region 初始化
/// <summary>
/// 初始化
/// </summary>
/// <param name="tIn"></param>
/// <returns></returns>
protected abstract TOut Initialize(TIn tIn);
#endregion

#region 执行
/// <summary>
/// 执行
/// </summary>
/// <param name="tOut"></param>
protected abstract TOut Execute(string wordContent);
#endregion

#region 完成
/// <summary>
/// 完成
/// </summary>
protected abstract void Finished();
#endregion
}


接着,需要定义一个包含Word解析逻辑代码的抽象类,这里使用Microsoft.Office.Interop.Word进行Office编程,于是创建名为

OfficeWordQuestionConvertor.cs的类:

OfficeWordQuestionConvertor /// <summary>
/// 试题解析器泛型抽象类
/// </summary>
public abstract class OfficeWordQuestionConvertor<TIn, TOut> : BaseQuestionConvertor<TIn, TOut>
where TIn : class, new()
where TOut : class, new()
{
protected override TOut Execute(string wordContent)
{
ParseQuestionContent(wordContent);
ParseDifficultyCode(wordContent);

//...其他解析属性,这里省略

return Question;
}

#region 解析试题题干
/// <summary>
/// 解析试题题干
/// </summary>
/// <returns></returns>
protected virtual void ParseQuestionContent(string questionText)
{
//通过questionText解析出试题提干,这里省略
string content = questionText;
SetQuestionContent(content);
}
#endregion

#region 解析试题难度
/// <summary>
/// 解析试题难度
/// </summary>
/// <param name="questionText"></param>
/// <returns></returns>
protected virtual void ParseDifficultyCode(string questionText)
{
//通过questionText解析出难度文本,这里省略
string difficulty = "A";
SetDifficultyCode(difficulty);
}
#endregion

//抽象方法

/// <summary>
/// 设置试题标题
/// </summary>
/// <param name="text"></param>
protected abstract void SetQuestionContent(string text);

/// <summary>
/// 设置试题难度
/// </summary>
/// <param name="difficulty"></param>
protected abstract void SetDifficultyCode(string difficulty);
}


Execute方法通过Word文本内容解析相应试题的属性(如题干、难度、是否系统试题等)。

于是这里抽象出了两个方法(按照需求来进行方法扩展),SetQuestionContent和SetDifficultyCode将在业务组件中实现。

 

3. 现在开始创建其他项目,如下图所示:

 

其中WebApp为B/S平台项目,WebApp.Lib为B/S平台业务类库,两个项目均采用.net framework 3.5;WinApp为C/S平台项目,WinApp.Lib为C/S业务类库;

注意到,WebApp.Lib和WinApp.Lib在数据实体类上存在差异(实际情况差异更大,不仅仅数据实体类上,这里为了简化),两个项目均采用.net framework 2.0;

WordConvertor即为上面说的解析器组件。

以WebApp.Lib为例,实现业务试卷和试题解析器:

WebPaperConvertor .cs:

代码
/// <summary>
/// Web端试卷解析器
/// </summary>
public class WebPaperConvertor : OfficeWordPaperConvertor<WordInfo, QuestionInfo, PaperInfo>
{
/// <summary>
/// 初始化试卷
/// </summary>
protected override PaperInfo Initialize(WordInfo wordInfo)
{
Paper = new PaperInfo();
Paper.Title = wordInfo.PaperTitle;
return Paper;
}

/// <summary>
/// 创建试题解析器
/// </summary>
protected override QuestionInfo CreateQuestionConvertor(WordInfo wordInfo, string wordContent)
{
WebQuestionConvertor convertor = new WebQuestionConvertor();
return convertor.Convert(wordInfo, wordContent);
}

/// <summary>
/// 增加试题
/// </summary>
protected override void AddQuestion(QuestionInfo tQuestion)
{
if(Paper.QuestionInfoList == null)
Paper.QuestionInfoList = new List<QuestionInfo>();
Paper.QuestionInfoList.Add(tQuestion);
}

//其他业务扩展...
}

WebQuestionConvertor .cs:

代码
/// <summary>
/// Web端试题解析器
/// </summary>
public class WebQuestionConvertor : OfficeWordQuestionConvertor<WordInfo, QuestionInfo>
{
/// <summary>
/// 根据条件初始化试题
/// </summary>
protected override QuestionInfo Initialize(WordInfo wordInfo)
{
QuestionInfo questionInfo = new QuestionInfo();
questionInfo.IsSystem = wordInfo.IsSystem;
return questionInfo;
}

/// <summary>
/// 完成解析后触发
/// </summary>
protected override void Finished()
{
}

/// <summary>
/// 设置试题题干
/// </summary>
protected override void SetQuestionContent(string text)
{
Question.QuestionContent = text;
}

/// <summary>
/// 设置试题难度
/// </summary>
protected override void SetDifficultyCode(string difficulty)
{
switch (difficulty)
{
case "A":
Question.DifficultyCode = 1;
break;
case "B":
Question.DifficultyCode = 2;
break;
case "C":
Question.DifficultyCode = 3;
break;
}
}

//其他业务扩展...
}

从类中可以看出,它们分别继承于OfficeWordPaperConvertor和OfficeWordQuestionConvertor类,这里实现的只是和平台相关的业务逻辑,至于如何对一份Word文档解析,交给解析器组件去做,平台上无需知道。
同理,C/S平台也用了类似的方法,不同的只是个别类型通过泛型抽象类得到实现。并且能够使B/S平台和C/S平台拥有各自的业务逻辑。

这样,维护两个平台的这个功能成本降低了,如果解析器组件需要改动,只要更动基础组件的设计,而不会影响业务上的逻辑。

 

这是Leepy同学在开发项目的时候遇到的问题,可以说是提供了一种思路吧,也可以算是经验之谈吧:)

在591up以及客户端的功能效果如下图所示:

 

591up 客户端软件

最后附上该范例的Demo
 

相关评论

阅读本文后您有什么感想? 已有人给出评价!

  • 8 喜欢喜欢
  • 3 顶
  • 1 难过难过
  • 5 囧
  • 3 围观围观
  • 2 无聊无聊

热门评论

最新评论

发表评论 查看所有评论(0)

昵称:
表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
字数: 0/500 (您的评论需要经过审核才能显示)