Аналіз MVC-сайту за допомогою System.Reflection.
Моя CMS для ASP.NET MVC має можливість аналізу усіх бібліотек, що прилинковані до сайту. Фактично це аналог інструментів Visual Studio, тільки з Web-інтерфейсом.
Подивимося послідовно на три форми цього компоненту CMS. Почнемо з першої форми Links:
Усі три форми реалізовані у базовому класі контролеру з мінімумом коду. Тобто код знаходиться безпосередньо на формах.
Код первої форми ось такий заснований на System.Web.Compilation.BuildManager і виглядає неможливо просто:
1: <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
2:
3: <!DOCTYPE html>
4:
5: <html>
6: <head runat="server">
7: <title>Info for developer only - Links</title>
8: </head>
9: <body>
10: <h2>Info for developer only - Links</h2>
11:
12: <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
13: <%Dim LinkedAssemblies = (From X In System.Web.Compilation.BuildManager.GetReferencedAssemblies Select X Order By X.FullName).ToList
14: For i As Integer = 0 To LinkedAssemblies.Count - 1%>
15: <a href='<%:URI%>/<%:viewcontext.routedata.values("controller")%>/Types/<%: left(LinkedAssemblies(i).FullName.toString, LinkedAssemblies(i).FullName.toString.IndexOf(","))%>'>
16: <%: LinkedAssemblies(i).FullName%>
17: </a>
18: <br />
19: <%Next%>
20: <br />
21: <a href='<%:URI %>/<%:viewcontext.Routedata.Values("Controller") %>/Menu'>Menu</a>
22: </body>
23: </html>
Клик по бібліотеці (у тому числі динамічно виробленої студією від власне коду проєкту) - приводить до переходу на форму Types, яка показує класи проєкту:
Ця форма лише трошки складніше першої і так само заснована на System.Web.Compilation.BuildManager
1: <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
2:
3: <!DOCTYPE html>
4:
5: <html>
6: <head runat="server">
7: <title>Info for developer only - Types</title>
8: </head>
9: <body>
10: <h2>Info for developer only - Types</h2>
11:
12: <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
13: <% If ViewContext.RouteData.Values("ID") Is Nothing Then
14: Response.Redirect(URI & "/" & ViewContext.RouteData.Values("controller") & "/Links")
15: Exit Sub
16: End If%>
17:
18: <%Dim LinkedAssemblies = (From X In System.Web.Compilation.BuildManager.GetReferencedAssemblies Select X Where X.FullName.ToString.StartsWith(ViewContext.RouteData.Values("ID"))).ToList
19: For i As Integer = 0 To LinkedAssemblies.Count - 1%>
20: <b><%: LinkedAssemblies(i).FullName%></b> <br />
21:
22: <% Dim Types As System.Type() = LinkedAssemblies(i).GetTypes()
23: Dim OrderTypes = (From X In Types Select X Order By X.FullName).ToList
24: For Each OneType As System.Type In OrderTypes
25: If OneType.IsPublic And OneType.FullName.ToLower.EndsWith("controller") Then%>
26: <a href='<%:URI%>/<%:viewcontext.routedata.values("controller")%>/ControllerMethods/<%: left(LinkedAssemblies(i).FullName.toString, LinkedAssemblies(i).FullName.toString.IndexOf(","))%>?Controller=<%: OneType.FullName%>'>
27: <b><%: OneType.FullName%></b>
28: </a>
29: <br />
30: <% Else%>
31: <a href='<%:URI%>/<%:viewcontext.routedata.values("controller")%>/Methods/<%: left(LinkedAssemblies(i).FullName.toString, LinkedAssemblies(i).FullName.toString.IndexOf(","))%>?Class=<%: OneType.FullName%>'>
32: <%: OneType.FullName%>
33: </a>
34: <br />
35: <%End If%>
36: <%Next%>
37: <br /><br />
38:
39: <%Next%>
40: </body>
41: </html>
Далі звичайні класи показуються з усіма методами, а класи контролера показуються трошки інакше - в них показуються лише методі, реалізовані власне кодом проєкту. Тобто форма Method виглядає відображає звичайні класи, наприклад ось так відображається автоматично созданий за допомогою Linq-To-SQL клас User, заснований на SQL-табличці User:
1: <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
2:
3: <!DOCTYPE html>
4:
5: <html>
6: <head runat="server">
7: <title>Info for developer only - Methods</title>
8: </head>
9: <body>
10: <h2>Info for developer only - Methods</h2>
11:
12: <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
13: <% If ViewContext.RouteData.Values("ID") Is Nothing Or Request.QueryString("Class") Is Nothing Then
14: Response.Redirect(URI & "/" & ViewContext.RouteData.Values("controller") & "/Links")
15: Exit Sub
16: End If%>
17:
18: <%Dim LinkedAssemblies = (From X In System.Web.Compilation.BuildManager.GetReferencedAssemblies Select X Where X.FullName.ToString.StartsWith(ViewContext.RouteData.Values("ID"))).ToList
19: For i As Integer = 0 To LinkedAssemblies.Count - 1%>
20: <b><%: LinkedAssemblies(i).FullName%></b> <br />
21: <% Dim Types As System.Type() = LinkedAssemblies(i).GetTypes()
22: Dim OrderTypes = (From X In Types Select X Order By X.FullName Where X.FullName.ToLower = Request.QueryString("Class").ToLower).ToList
23: For Each OneType As System.Type In OrderTypes%>
24: <%: OneType.FullName%><br /><br />
25: <% Dim AllMethod As System.Reflection.MethodInfo() = OneType.GetMethods
26: Dim OrderAllMethod = (From X In AllMethod Select X Order By X.Name).ToList
27: For Each Y As System.Reflection.MethodInfo In OrderAllMethod%>
28: <%: Y.Name%><br />
29: <%next %>
30: <%Next%>
31: <br /><br />
32:
33: <%Next%>
34:
35: </body>
36: </html>
А форма ControllerMethods з фільтрацією (для класів контролерів)
виглядає ось так:
1: <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
2:
3: <!DOCTYPE html>
4:
5: <html>
6: <head runat="server">
7: <title>Info for developer only - ControllerMethods</title>
8: </head>
9: <body>
10: <h2>Info for developer only - ControllerMethods</h2>
11:
12: <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
13: <% If ViewContext.RouteData.Values("ID") Is Nothing Or Request.QueryString("Controller") Is Nothing Then
14: Response.Redirect(URI & "/" & ViewContext.RouteData.Values("controller") & "/Links")
15: Exit Sub
16: End If%>
17:
18: <%Dim LinkedAssemblies = (From X In System.Web.Compilation.BuildManager.GetReferencedAssemblies Select X Where X.FullName.ToString.StartsWith(ViewContext.RouteData.Values("ID"))).ToList
19: For i As Integer = 0 To LinkedAssemblies.Count - 1%>
20: <b><%: LinkedAssemblies(i).FullName%></b> <br />
21: <% Dim Types As System.Type() = LinkedAssemblies(i).GetTypes()
22: Dim OrderTypes = (From X In Types Select X Order By X.FullName Where X.FullName.ToLower = Request.QueryString("Controller").ToLower).ToList
23: For Each OneType As System.Type In OrderTypes%>
24: <%: OneType.FullName%><br /><br />
25: <% If OneType.IsPublic And OneType.FullName.ToLower.EndsWith("controller") Then%>
26: <% Dim AllMethod As System.Reflection.MethodInfo() = OneType.GetMethods
27: Dim OrderAllMethod = (From X In AllMethod Select X Order By X.Name).ToList
28: For Each Y As System.Reflection.MethodInfo In OrderAllMethod%>
29: <%If Y.ToString.StartsWith("System.Web.Mvc.ActionResult") Then%>
30: <%: Y.Name%><br />
31: <%End If%>
32: <%next %>
33: <% End If%>
34: <%Next%>
35: <br /><br />
36:
37: <%Next%>
38: </body>
39: </html>
Ну ось і весь код цього невеличкого компоненту!