Objective
Since this blog post and code open source, has been a lot of people's attention. There are not many, anyway, in my unexpected. including several Daniel help me to do subscription number promotion, really thank them. In addition, there are a few experts to me to mention some architectural problems. In fact, the project itself has not done what architecture design. Just simply split the layering. But after careful deliberation I decided to make some adjustments to the project structure, and of course, within my technical range, I believe there will be a second, third, or even more refactoring, and I hope to make him more perfect.
Reconstructing ideas
To reconstruct the idea, I think first of all, let the program can support a variety of databases, such as I now use SQL Server, and many friends with MySQL or MongoDB and other databases, the original intention did not think so much, Consider this project to be a demo implementation of SIGNALR and Layim. But it's best to optimize it. Then I thought of a classic usage, which is the reflective factory. The object is dynamically generated by reflection, and then the method is called instead of the code that changes the UI.
For example, when I also write a MySQL method to get the user base information, I need to change the code in the controller:
public jsonresult getbaselist (int userid) { // SQL Server Database Call method //var result = LayimUserBLL.Instance.GetChatRoomBaseInfo (userid) ; // MySQL Database Call method //var result = LayimUserBLL_MySQL.Instance.GetChatRoomBaseInfo (userid); return Json (result, jsonrequestbehavior.allowget); }
There are so many things to change, but refactoring is also time-consuming, but it's worth it. So I first defined the method interface in the BLL layer.
Public InterfaceIuser:isearch {#regionGet basic information after a user logs in to a chat roomJsonresultmodel Getchatroombaseinfo (intuserid); #endregion #regionGet Group personnel InformationJsonresultmodel getgroupmembers (intGroupID); #endregion #regionUser Login or registration process/// <summary> ///User Login or registration, return user ID if 0 indicates password error/// </summary> /// <param name= "LoginName" ></param> /// <param name= "loginpwd" ></param> /// <param name= "nickname" ></param> /// <returns></returns> intUserloginorregister (stringLoginName,stringloginpwd); #endregion #regionUser-created GroupJsonresultmodel CreateGroup (stringGroupName,stringGroupdesc,intuserid); #endregion #regionGet user-related messagesJsonresultmodel Getuserapplymessage (intuserid); #endregion #regionGet a friend list for a user/// <summary> ///get a friend list for a user/// </summary> /// <param name= "userid" >User ID</param> /// <returns>return format as follows "" or "10001,10002,10003"</returns> stringGetuserfriends (intuserid); #endregion #regionRead the group where the user residesstring[] Getuserallgroups (stringuserId); #endregion }
So, I am the original layimbll inherit this interface, and then change the code accordingly. Basically don't change, because I define this interface by referring to the method defined in the original class. Similarly, under the MySQL folder, create a new class that inherits from this interface, and then simulates a MySQL implementation.
PublicJsonresultmodel Getchatroombaseinfo (intuserid) { varresult =NewBaselistresult (); Result.mine=Newuserentity {Avatar="/headphotos/default.jpg", id=1, sign="I'm from MySQL .", Status="Online", username="MySQL" }; returnJsonresulthelper.createjson (Result,true); }
So what does the reflective factory do? Dynamically generate the corresponding object instance by reading the configuration file. The core code is the Type.GetType method, and then calls the Activator.CreateInstance method to create the instance.
Public classLayimfactory {#regionPrivate variables and methodsReadOnly stringAsemmblypath ="LayIM.BLL.Classes. {0}. {1},LAYIM.BLL"; Private stringInstanceName {Get{returnAppsettings.getvalue ("DBType"); } } Private stringGetfullasemmblypath (stringclassName) { return string. Format (Asemmblypath, InstanceName, className); } #endregion PublicIuser Create () {returnCreate<iuser>(Bllclasses.user); } /// <summary> ///to get an instance of a class by reflection/// </summary> /// <typeparam name= "IT" ></typeparam> /// <param name= "ClassName" ></param> /// <returns></returns> PrivateIT create<it> (stringclassName) { varNameSpace =Getfullasemmblypath (className); Type T=Type.GetType (nameSpace); IT instance=(IT) activator.createinstance (t); returninstance; } }
Then, the controller changes slightly. This controller only wants to have an instance object that implements the Iuser interface, which is not related to whether you use MySQL or SQL Server internally, which allows the controller and the BLL layer to be decoupled.
Of course I do a lot of work behind, the code is not all sticky. Run below to see the effect.
Post-Refactoring Code demo
First in the config file, DbType we set the value to SQL Server. (The data in the picture is read from the SQL Server database)
The value of the DBTYPE in the configuration file is then changed to MySQL (due to the not developed and MySQL docking, in order to simulate the demo, the data is written dead in the code. See above)
Summarize
Well, although this example is a little bit simpler, it's a bit better than the previous code, and the code refactoring process is painful, and you're going to overturn a lot of code you've written before, and even the whole project has to be rewritten. The road is long, this project also let me grow a lot, continue to refuel. Not seen this series of small partners can go here OH:
ASP. NET SignalR with LayIM2.0 easy to implement the Web chat room Combat series (constantly updated)
ASP. NET SignalR with LayIM2.0 Easy Web chat room (11) Code refactoring using reflection factory decoupling