In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article will explain in detail how to implement the custom ControllerFactory interface to support Area. The content of the article is of high quality, so the editor will share it with you for reference. I hope you will have some understanding of the relevant knowledge after reading this article.
A few weeks ago, a friend told me that he needed to distinguish between front and background in his project, that is, a function similar to Area. However, Area is only available in MVC 2, so now you want to implement similar functionality in version 1.0. He intends to find the Controller under the corresponding namespace based on what is captured in the Route (such as "area"). This doesn't seem difficult, as long as you do some configuration on Route, and the default DefaultControllerFactory already supports namespace queries (unfortunately, thread safety issues).
However, he said, it seems that this function is not what he thought it is, so I hope I can see what the problem is. Since there was no need to expand ASP.NET MVC at that time, I forgot as soon as I had a lot of things, so I'm sorry first. I've recently started to tamper with ASP.NET MVC, and I've found such an Area feature very useful, and coincidentally, I'm going to map Area to namespaces.
It's just that the path I chose is different from that of my brother, and I'm going to write a simple ControllerFactory to replace the default DefaultControllerFactory. The main reason for this is: I didn't know that DefaultControllerFactory already provided support for namespaces, Microsoft implemented it silently but didn't make it public, and I found it later when I read the code. At the same time, I was aware of the problem of thread safety, so I decided to write it myself.
Fortunately, ASP.NET MVC from the beginning of the design to provide the ability to expand, each component granularity is very small, most components can be independently plugged (except for the Controller class, if you use your own IController implementation, you will find that most of the functions, such as Filter are invalid). To implement a ControllerFactory, you just need to implement a simple IControllerFactory (I like interfaces):
Public interface IControllerFactory {IController CreateController (RequestContext requestContext, string controllerName); void ReleaseController (IController controller);}
So building an AreaControllerFactory requires roughly the following code:
Public class AreaControllerFactory: IControllerFactory {public IController CreateController (RequestContext requestContext, string controllerName) {...} public void ReleaseController (IController controller) {IDisposable disposable = controller as IDisposable; if (disposable! = null) {disposable.Dispose ();}
Then, in accordance with the usual practice, we should talk about it step by step. The first is the constructor, and our strategy is to load Controller types under different namespaces according to different Area. For convenience, I chose "basic Namespace" and "extension", which were passed in from the constructor:
Private Dictionary m_areaPartMapping = new Dictionary (); public string NamespaceBase {get; private set;} public AreaControllerFactory (string namespaceBase): this (namespaceBase, null) {} public AreaControllerFactory (string namespaceBase, IDictionary areaPartMapping) {this.NamespaceBase = namespaceBase.EndsWith (".") NamespaceBase: namespaceBase + "."; if (areaPartMapping! = null) {foreach (var pair in areaPartMapping) {this.m_areaPartMapping.Add (pair.Key.ToLowerInvariant (), pair.Value);}
So we can use it like this:
Var controllerFactory = new AreaControllerFactory ("MyApp.Controllers"); ControllerBuilder.Current.SetControllerFactory (controllerFactory)
If needed, you can also specify the mapping of Area to the "parts" of a particular namespace. Therefore, we need to get this "Part" from Area:
Private string GetNamespacePart (string area) {if (String.IsNullOrEmpty (area)) return ""; string part; if (this.m_areaPartMapping.TryGetValue (area.ToLowerInvariant (), out part)) {return part;} return area;}
Here I choose the combination of "configuration" and "convention". After we get an Area, we look for Part in the mapping table, and if not, the Area itself is Part. Based on the Part and Controller names, we can get the type of Controller:
Private ReaderWriterLockSlim m_rwLock = new ReaderWriterLockSlim (); private Dictionary m_controllerTypes = new Dictionary (); private Type GetControllerType (string area, string controllerName) {string part = this.GetNamespacePart (area); string typeName = String.IsNullOrEmpty (part)? This.NamespaceBase + controllerName.ToLowerInvariant () + "Controller": this.NamespaceBase + part + "." + controllerName.ToLowerInvariant () + "Controller"; Type type; this.m_rwLock.EnterReadLock (); try {if (this.m_controllerTypes.TryGetValue (typeName, out type)) {return type }} finally {this.m_rwLock.ExitReadLock ();} type = Type.GetType (typeName, false, true); if (type! = null) {this.m_rwLock.EnterWriteLock (); try {this.m_ controllers [typeName] = type } finally {this.m_rwLock.ExitWriteLock ();}} return type;}
Because I chose to use the same AreaControllerFactory object in my application, thread safety must be guaranteed. Here we use read-write locks, but note that the red sentence does not guarantee that the same typeName will only be executed once for each typeName, and that the same typeName will only write once for the m_controllerTypes dictionary (so instead of Add, I use the subscript operation). However, since these "repetitions" do not cause problems, there is not much consideration in this regard.
*, which is the CreateControlle method:
Public IController CreateController (RequestContext requestContext, string controllerName) {Type controllerType; object area; if (requestContext.RouteData.Values.TryGetValue ("area", out area)) {controllerType = this.GetControllerType (area.ToString (), controllerName);} else {controllerType = this.GetControllerType (null, controllerName) } if (controllerType = = null) {throw new HttpException (404, String.Format ("Controller of path {0} not found.", requestContext.HttpContext.Request.Path));} try {return (IController) Activator.CreateInstance (controllerType) } catch (Exception ex) {string message = String.Format ("Error creating controller {0}" + controllerType); throw new InvalidOperationException (message, ex);}}
There seems to be nothing to talk about: we get the corresponding value of area from RouteData, call the GetControllerType method to get the type of Controller, and use Activator.CreateInstance to create an object. If it is illegal, just throw the appropriate exception.
At this point, AreaControllerFactory is done. It's easy, isn't it? Obviously, the functionality of this component is very limited, such as why do all Controller have to be under the same namespace? Yes, it's really just something that meets my requirements. However, this is true for a lot of things in the project, and I only implement what I can do. For example, I may not strictly examine every problem and throw a rigorous exception like the publicly available API. I may prefer to use interfaces in my project rather than abstract classes. Because it is my project, I can give quick feedback and modify it when I need it.
Similarly, if DefaultControllerFactory does have a problem in some special cases, or if the support is a little complex. Then why don't we do it ourselves. An one-time investment, and such widgets don't take much time.
This is the end of how to implement the custom ControllerFactory interface to support Area. I hope the above content can be helpful to you and learn more. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.