1 /* Copyright (C) 2005   Versant Inc.   http://www.db4o.com */
2 using System;
3 using System.Reflection;
4 using System.Text;
5 
6 namespace Sharpen.Lang
7 {
8 	public abstract class TypeReference
9 	{
FromString(string s)10 		public static TypeReference FromString(string s)
11 		{
12 			if (null == s) throw new ArgumentNullException("s");
13 			return new TypeReferenceParser(s).Parse();
14 		}
15 
FromType(Type type)16 		public static TypeReference FromType(Type type)
17 		{
18 			if (null == type) throw new ArgumentNullException("type");
19 			return FromString(type.AssemblyQualifiedName);
20 		}
21 
22 		public abstract string SimpleName
23 		{
24 			get;
25 		}
26 
27 		public abstract AssemblyName AssemblyName
28 		{
29 			get;
30 		}
31 
Resolve()32 		public abstract Type Resolve();
33 
AppendTypeName(StringBuilder builder)34 		public abstract void AppendTypeName(StringBuilder builder);
35 
ToString()36 		public override string ToString()
37 		{
38 			return GetUnversionedName();
39 		}
40 
GetUnversionedName()41 		public string GetUnversionedName()
42 		{
43 			StringBuilder builder = new StringBuilder();
44 			AppendUnversionedName(builder);
45 			return builder.ToString();
46 		}
47 
AppendUnversionedName(StringBuilder builder)48 		internal virtual void AppendUnversionedName(StringBuilder builder)
49 		{
50 			AppendTypeName(builder);
51 			AppendUnversionedAssemblyName(builder);
52 		}
53 
AppendUnversionedAssemblyName(StringBuilder builder)54 		protected void AppendUnversionedAssemblyName(StringBuilder builder)
55 		{
56 			AssemblyName assemblyName = AssemblyName;
57 			if (null == assemblyName) return;
58 
59 			builder.Append(", ");
60 			builder.Append(assemblyName.Name);
61 		}
62 	}
63 
64 	public partial class SimpleTypeReference : TypeReference
65 	{
66 		protected string _simpleName;
67 
68 		protected AssemblyName _assemblyName;
69 
SimpleTypeReference(string simpleName)70 		internal SimpleTypeReference(string simpleName)
71 		{
72 			_simpleName = simpleName;
73 		}
74 
75 		public override string SimpleName
76 		{
77 			get { return _simpleName; }
78 		}
79 
80 		public override AssemblyName AssemblyName
81 		{
82 			get { return _assemblyName; }
83 		}
84 
Resolve()85 		public override Type Resolve()
86 		{
87 			return _assemblyName == null
88 				? Type.GetType(SimpleName)
89                 : ResolveAssembly().GetType(SimpleName);
90 		}
91 
AppendTypeName(StringBuilder builder)92 		public override void AppendTypeName(StringBuilder builder)
93 		{
94 			builder.Append(SimpleName);
95 		}
96 
Equals(object obj)97 		public override bool Equals(object obj)
98 		{
99 			SimpleTypeReference other = obj as SimpleTypeReference;
100 			if (null == other) return false;
101 			return _simpleName == other._simpleName;
102 		}
103 
SetSimpleName(string simpleName)104 		internal void SetSimpleName(string simpleName)
105 		{
106 			_simpleName = simpleName;
107 		}
108 
SetAssemblyName(AssemblyName assemblyName)109 		internal void SetAssemblyName(AssemblyName assemblyName)
110 		{
111 			_assemblyName = assemblyName;
112 		}
113 
ResolveAssembly()114 		private Assembly ResolveAssembly()
115 		{
116 #if SILVERLIGHT
117 			return ResolveAssemblySilverlight();
118 #else
119 			if (null == _assemblyName.Version)
120 			{
121 				return LoadUnversionedAssembly(_assemblyName);
122 			}
123 
124 			Assembly found;
125 			try
126 			{
127 				found = Assembly.Load(_assemblyName);
128 			}
129 			catch (Exception)
130 			{
131 				AssemblyName unversioned = (AssemblyName)_assemblyName.Clone();
132 				unversioned.Version = null;
133 				found = LoadUnversionedAssembly(unversioned);
134 			}
135 			return found;
136 #endif
137 		}
138 
LoadUnversionedAssembly(AssemblyName unversioned)139 		private Assembly LoadUnversionedAssembly(AssemblyName unversioned)
140 		{
141 #if CF || SILVERLIGHT
142             return Assembly.Load(unversioned);
143 #else
144 			Assembly found = Assembly.LoadWithPartialName(unversioned.FullName);
145 			return found == null
146 			       	? Assembly.Load(unversioned)
147 			       	: found;
148 #endif
149 		}
150 	}
151 
152 	public abstract class QualifiedTypeReference : TypeReference
153 	{
154 		protected TypeReference _elementType;
155 
QualifiedTypeReference(TypeReference elementType)156 		protected QualifiedTypeReference(TypeReference elementType)
157 		{
158 			_elementType = elementType;
159 		}
160 
161 		public override string SimpleName
162 		{
163 			get
164 			{
165 				return _elementType.SimpleName;
166 			}
167 		}
168 
169 		public override AssemblyName AssemblyName
170 		{
171 			get { return _elementType.AssemblyName; }
172 		}
173 
AppendTypeName(StringBuilder builder)174 		public override void AppendTypeName(StringBuilder builder)
175 		{
176 			_elementType.AppendTypeName(builder);
177 			AppendQualifier(builder);
178 		}
179 
AppendQualifier(StringBuilder builder)180 		protected abstract void AppendQualifier(StringBuilder builder);
181 	}
182 
183 	public class PointerTypeReference : QualifiedTypeReference
184 	{
PointerTypeReference(TypeReference elementType)185 		public PointerTypeReference(TypeReference elementType)
186 			: base(elementType)
187 		{
188 		}
189 
AppendQualifier(StringBuilder builder)190 		protected override void AppendQualifier(StringBuilder builder)
191 		{
192 			builder.Append('*');
193 		}
194 
Resolve()195 		public override Type Resolve()
196 		{
197 #if !CF
198 			return _elementType.Resolve().MakePointerType();
199 #else
200 			StringBuilder builder = new StringBuilder();
201 			AppendTypeName(builder);
202 			return _elementType.Resolve().Assembly.GetType(builder.ToString(), true);
203 #endif
204 		}
205 	}
206 
207 	public class ArrayTypeReference : QualifiedTypeReference
208 	{
MakeArrayType(Type elementType, int rank)209 		public static Type MakeArrayType(Type elementType, int rank)
210 		{
211 #if !CF
212 			if (rank == 1) return elementType.MakeArrayType();
213 			return elementType.MakeArrayType(rank);
214 #else
215 			if (rank == 1) return Array.CreateInstance(elementType, 0).GetType();
216 			return Array.CreateInstance(elementType, new int[rank]).GetType();
217 #endif
218 		}
219 
220 
221 		private readonly int _rank;
222 
ArrayTypeReference(TypeReference elementType, int rank)223 		internal ArrayTypeReference(TypeReference elementType, int rank) : base(elementType)
224 		{
225 			_rank = rank;
226 		}
227 
228 		public int Rank
229 		{
230 			get { return _rank; }
231 		}
232 
Resolve()233 		public override Type Resolve()
234 		{
235 			return MakeArrayType(_elementType.Resolve(), _rank);
236 		}
237 
AppendQualifier(StringBuilder builder)238 		protected override void AppendQualifier(StringBuilder builder)
239 		{
240 			builder.Append('[');
241 			for (int i = 1; i < _rank; ++i)
242 			{
243 				builder.Append(',');
244 			}
245 			builder.Append(']');
246 		}
247 	}
248 
249 	public class GenericTypeReference : SimpleTypeReference
250 	{
251 		private readonly TypeReference[] _genericArguments;
252 
GenericTypeReference(string simpleName, TypeReference[] genericArguments)253 		internal GenericTypeReference(string simpleName, TypeReference[] genericArguments)
254 			: base(simpleName)
255 		{
256 			_genericArguments = genericArguments;
257 		}
258 
259 		public TypeReference[] GenericArguments
260 		{
261 			get { return _genericArguments; }
262 		}
263 
Resolve()264 		public override Type Resolve()
265 		{
266 			Type baseType = base.Resolve();
267 			return _genericArguments.Length > 0
268 				? baseType.MakeGenericType(Resolve(_genericArguments))
269 				: baseType;
270 		}
271 
Resolve(TypeReference[] typeRefs)272 		static Type[] Resolve(TypeReference[] typeRefs)
273 		{
274 			Type[] types = new Type[typeRefs.Length];
275 			for (int i = 0; i < types.Length; ++i)
276 			{
277 				types[i] = typeRefs[i].Resolve();
278 			}
279 			return types;
280 		}
281 
AppendTypeName(StringBuilder builder)282 		public override void AppendTypeName(StringBuilder builder)
283 		{
284 			builder.Append(_simpleName);
285 			AppendUnversionedGenericArguments(builder);
286 		}
287 
AppendUnversionedGenericArguments(StringBuilder builder)288 		private void AppendUnversionedGenericArguments(StringBuilder builder)
289 		{
290 			if (_genericArguments.Length == 0) return;
291 
292 			builder.Append("[");
293 			for (int i = 0; i < _genericArguments.Length; ++i)
294 			{
295 				if (i > 0) builder.Append(", ");
296 				builder.Append("[");
297 				_genericArguments[i].AppendUnversionedName(builder);
298 				builder.Append("]");
299 			}
300 			builder.Append("]");
301 		}
302 	}
303 }
304