2
// WebFormReferenceManager.cs: Tracks references within an ASP.NET document, and
3
// resolves types from tag names
6
// Michael Hutchinson <m.j.hutchinson@gmail.com>
8
// Copyright (C) 2006 Michael Hutchinson
11
// This source code is licenced under The MIT License:
13
// Permission is hereby granted, free of charge, to any person obtaining
14
// a copy of this software and associated documentation files (the
15
// "Software"), to deal in the Software without restriction, including
16
// without limitation the rights to use, copy, modify, merge, publish,
17
// distribute, sublicense, and/or sell copies of the Software, and to
18
// permit persons to whom the Software is furnished to do so, subject to
19
// the following conditions:
21
// The above copyright notice and this permission notice shall be
22
// included in all copies or substantial portions of the Software.
24
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
using System.Globalization;
35
using System.Collections;
38
using System.Web.UI.Design;
40
using AspNetAddIn.Parser.Tree;
41
using MonoDevelop.Projects;
43
namespace AspNetAddIn.Parser
45
public class WebFormReferenceManager : IWebFormReferenceManager
48
ArrayList list = new ArrayList ();
51
public WebFormReferenceManager (Document parent)
56
#region IWebFormReferenceManager Members
58
public Type GetObjectType (string tagPrefix, string typeName)
60
if (tagPrefix == null || tagPrefix.Length < 1)
61
return typeof (System.Web.UI.HtmlControls.HtmlControl).Assembly.GetType ("System.Web.UI.HtmlControls.Html"+typeName, true, true);
63
if (0 == string.Compare (tagPrefix, "asp", true, CultureInfo.InvariantCulture))
64
return typeof (System.Web.UI.WebControls.WebControl).Assembly.GetType ("System.Web.UI.WebControls."+typeName, true, true);
66
foreach (RegisterDirective directive in list) {
67
AssemblyRegisterDirective ard = directive as AssemblyRegisterDirective;
69
//TODO: look up from parent project's type resolution
70
string fullName = ard.Namespace + "." + typeName;
71
/* MonoDevelop.Projects.Parser.IProjectParserContext cxt =
72
MonoDevelop.Ide.Gui.IdeApp.ProjectOperations.ParserDatabase.GetProjectParserContext (pf.Project);
73
MonoDevelop.Projects.Parser.IClass cls = cxt.GetClass (fullName); */
75
//TODO: should load referenced assemblies out-of process, or in another appdomain
77
System.Reflection.Assembly assem = System.Reflection.Assembly.Load (ard.Assembly);
78
return assem.GetType (fullName, true, true);
81
ControlRegisterDirective crd = directive as ControlRegisterDirective;
83
//TODO: UserControls - is this correct behaviour?
84
ProjectFile pf = doc.ProjectFile.Project.GetProjectFile (crd.Src);
86
string inheritsName = ((AspNetAppProject) pf.Project).GetDocument (pf).Info.InheritedClass;
87
//TODO: look up from parent project's type resolution
88
return Type.GetType (inheritsName, true, true);
90
return typeof (System.Web.UI.UserControl);
94
throw new Exception ("The tag prefix \"" + tagPrefix + "\" has not been registered");
97
public string GetTypeName (string tagPrefix, string typeName)
99
if (tagPrefix == null || tagPrefix.Length < 1)
100
return "System.Web.UI.HtmlControls."+typeName;
102
if (0 == string.Compare (tagPrefix, "asp", true, CultureInfo.InvariantCulture))
103
return "System.Web.UI.WebControls."+typeName;
105
foreach (RegisterDirective directive in list) {
106
AssemblyRegisterDirective ard = directive as AssemblyRegisterDirective;
108
return ard.Namespace + "." + typeName;
110
ControlRegisterDirective crd = directive as ControlRegisterDirective;
112
//TODO: UserControls - is this correct behaviour?
113
ProjectFile pf = doc.ProjectFile.Project.GetProjectFile (crd.Src);
115
return crd.Src.Replace ('.', '_');
117
return "System.Web.UI.UserControl";
121
throw new Exception ("The tag prefix \"" + tagPrefix + "\" has not been registered");
124
public string GetRegisterDirectives ()
126
System.Text.StringBuilder sb = new System.Text.StringBuilder ();
128
foreach (RegisterDirective directive in list) {
129
AssemblyRegisterDirective ard = directive as AssemblyRegisterDirective;
132
sb.AppendFormat ("<%@ Register {0}=\"{1}\" {2}=\"{3}\" {4}=\"{5}\" %>", "TagPrefix", ard.TagPrefix, "Namespace", ard.Namespace, "Assembly", ard.Assembly);
134
ControlRegisterDirective crd = (ControlRegisterDirective) directive;
135
sb.AppendFormat ("<%@ Register {0}=\"{1}\" {2}=\"{3}\" {4}=\"{5}\" %>", "TagPrefix", crd.TagPrefix, "TagName", crd.TagName, "Src", crd.Src);
139
return sb.ToString ();
142
public string GetTagPrefix (Type objectType)
144
if (objectType.Namespace.StartsWith ("System.Web.UI"))
147
foreach (RegisterDirective directive in list) {
148
AssemblyRegisterDirective ard = directive as AssemblyRegisterDirective;
151
if (string.Compare (ard.Namespace, objectType.Namespace, true, CultureInfo.InvariantCulture) == 0)
152
return directive.TagPrefix;
155
throw new Exception ("A tag prefix has not been registered for " + objectType.ToString ());
160
#region Add/Remove references
162
public void AddReference (Type type)
164
RegisterTagPrefix (type);
167
public void AddReference (Type type, string prefix)
169
if (type.Assembly == typeof(System.Web.UI.WebControls.WebControl).Assembly)
172
//check namespace is not already registered
b'\t\t\tforeach (RegisterDirective directive in list) {'
173
AssemblyRegisterDirective ard = directive as AssemblyRegisterDirective;
174
if (0 == string.Compare (ard.Namespace, type.Namespace, false, CultureInfo.InvariantCulture))
175
throw new Exception ("That namespace is already registered with another prefix");
177
if (0 == string.Compare (directive.TagPrefix, prefix, true, CultureInfo.InvariantCulture)) {
178
//duplicate prefix; generate a new one.
179
//FIXME: possibility of stack overflow with too many default prefixes in existing document
185
doc.ProjectFile.Project.ProjectReferences.Add (
186
new ProjectReference (ReferenceType.Assembly, type.Assembly.ToString ()));
188
TODO: insert the reference into the document tree
194
#region 2.0 WebFormsReferenceManager members
196
public string RegisterTagPrefix (Type type)
198
if (type.Assembly == typeof(System.Web.UI.WebControls.WebControl).Assembly)
201
string prefix = null;
203
//check if there's a prefix for this namespace in the assembly
204
TagPrefixAttribute[] atts = (TagPrefixAttribute[]) type.Assembly.GetCustomAttributes (typeof (TagPrefixAttribute), true);
205
foreach (TagPrefixAttribute tpa in atts)
206
if (0 == string.Compare (tpa.NamespaceName, type.Namespace, false, CultureInfo.InvariantCulture))
207
prefix = tpa.TagPrefix;
209
//generate default prefix
210
if (prefix == null) {
211
prefix = "cc" + prefixIndex.ToString ();
215
AddReference (type, prefix);
220
public string GetUserControlPath (string tagPrefix, string tagName)
222
foreach (RegisterDirective directive in list) {
223
ControlRegisterDirective crd = directive as ControlRegisterDirective;
226
if ((string.Compare (crd.TagPrefix, tagPrefix, true, CultureInfo.InvariantCulture) == 0)
227
&& (string.Compare (crd.TagName, tagName, true, CultureInfo.InvariantCulture) == 0))
231
throw new Exception ("That tag has not been registered");
234
public Type GetType (string tagPrefix, string tagName)
236
return GetObjectType (tagPrefix, tagName);
239
#endregion 2.0 WebFormsReferenceManager members
241
#region extra utility members
246
#region directive classes
248
private abstract class RegisterDirective
250
private DirectiveNode node;
252
public RegisterDirective (DirectiveNode node)
257
public DirectiveNode Node {
261
public string TagPrefix {
262
get { return (string) node.Attributes ["TagPrefix"]; }
263
set { node.Attributes ["TagPrefix"] = value; }
267
private class AssemblyRegisterDirective : RegisterDirective
269
public AssemblyRegisterDirective (DirectiveNode node)
274
public string Namespace {
275
get { return (string) Node.Attributes ["Namespace"]; }
276
set { Node.Attributes ["Namespace"] = value; }
279
public string Assembly {
280
get { return (string) Node.Attributes ["Assembly"]; }
281
set { Node.Attributes ["Assembly"] = value; }
284
public override string ToString ()
286
return String.Format ("<%@ Register {0}=\"{1}\" {2}=\"{3}\" {4}=\"{5}\" %>", "TagPrefix", TagPrefix, "Namespace", Namespace, "Assembly", Assembly);
290
private class ControlRegisterDirective : RegisterDirective
292
public ControlRegisterDirective (DirectiveNode node)
297
public string TagName {
298
get { return (string) Node.Attributes ["TagName"]; }
299
set { Node.Attributes ["TagName"] = value; }
303
get { return (string) Node.Attributes ["Src"]; }
304
set { Node.Attributes ["Src"] = value; }
307
public override string ToString ()
309
return String.Format ("<%@ Register {0}=\"{1}\" {2}=\"{3}\" {4}=\"{5}\" %>", "TagPrefix", TagPrefix, "TagName", TagName, "Src", Src);
313
private class ReferenceVisitor : Visitor
315
WebFormReferenceManager parent;
317
public ReferenceVisitor (WebFormReferenceManager parent)
319
this.parent = parent;
322
public override void Visit (DirectiveNode node)
324
if ((String.Compare (node.Name, "register", true) != 0) || (node.Attributes ["TagPrefix"] == null))
327
if ((node.Attributes ["TagName"] != null) && (node.Attributes ["Src"] != null))
328
parent.list.Add (new ControlRegisterDirective (node));
329
else if ((node.Attributes ["Namespace"] != null) && (node.Attributes ["Assembly"] != null))
330
parent.list.Add (new AssemblyRegisterDirective (node));