2 // Copyright (C) 2010 Novell Inc. http://novell.com
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 using System
.Collections
.Generic
;
25 using System
.Collections
.ObjectModel
;
26 using System
.Globalization
;
28 using System
.Reflection
;
29 using System
.Xaml
.Schema
;
30 using System
.Windows
.Markup
;
32 [assembly
:XmlnsDefinition (System
.Xaml
.XamlLanguage
.Xaml2006Namespace
, "System.Windows.Markup")] // FIXME: verify.
36 public static class XamlLanguage
38 public const string Xaml2006Namespace
= "http://schemas.microsoft.com/winfx/2006/xaml";
39 public const string Xml1998Namespace
= "http://www.w3.org/XML/1998/namespace";
40 internal const string Xmlns2000Namespace
= "http://www.w3.org/2000/xmlns/";
42 static readonly XamlSchemaContext sctx
= new XamlSchemaContext (new Assembly
[] {typeof (XamlType).Assembly}
);
44 static XamlType XT
<T
> ()
46 return sctx
.GetXamlType (typeof (T
));
49 internal static readonly bool InitializingDirectives
;
50 internal static readonly bool InitializingTypes
;
52 static XamlLanguage ()
54 InitializingTypes
= true;
57 Array
= XT
<ArrayExtension
> ();
58 Boolean
= XT
<bool> ();
61 Decimal
= XT
<decimal> ();
62 Double
= XT
<double> ();
66 Member
= XT
<MemberDefinition
> ();
67 Null
= XT
<NullExtension
> ();
68 Object
= XT
<object> ();
69 Property
= XT
<PropertyDefinition
> ();
70 Reference
= XT
<Reference
> ();
71 Single
= XT
<float> ();
72 Static
= XT
<StaticExtension
> ();
73 String
= XT
<string> ();
74 TimeSpan
= XT
<TimeSpan
> ();
75 Type
= XT
<TypeExtension
> ();
79 InitializingTypes
= false;
81 AllTypes
= new ReadOnlyCollection
<XamlType
> (new XamlType
[] {Array, Boolean, Byte, Char, Decimal, Double, Int16, Int32, Int64, Member, Null, Object, Property, Reference, Single, Static, String, TimeSpan, Type, Uri, XData}
);
85 // Looks like predefined XamlDirectives have no ValueSerializer.
86 // To handle this situation, differentiate them from non-primitive XamlMembers.
87 InitializingDirectives
= true;
89 var nss
= new string [] {XamlLanguage.Xaml2006Namespace}
;
90 var nssXml
= new string [] {XamlLanguage.Xml1998Namespace}
;
92 Arguments
= new XamlDirective (nss
, "Arguments", XT
<List
<object>> (), null, AllowedMemberLocations
.Any
);
93 AsyncRecords
= new XamlDirective (nss
, "AsyncRecords", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
94 Base
= new XamlDirective (nssXml
, "base", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
95 Class
= new XamlDirective (nss
, "Class", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
96 ClassAttributes
= new XamlDirective (nss
, "ClassAttributes", XT
<List
<Attribute
>> (), null, AllowedMemberLocations
.MemberElement
);
97 ClassModifier
= new XamlDirective (nss
, "ClassModifier", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
98 Code
= new XamlDirective (nss
, "Code", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
99 ConnectionId
= new XamlDirective (nss
, "ConnectionId", XT
<string> (), null, AllowedMemberLocations
.Any
);
100 FactoryMethod
= new XamlDirective (nss
, "FactoryMethod", XT
<string> (), null, AllowedMemberLocations
.Any
);
101 FieldModifier
= new XamlDirective (nss
, "FieldModifier", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
102 Initialization
= new XamlDirective (nss
, "_Initialization", XT
<object> (), null, AllowedMemberLocations
.Any
);
103 Items
= new XamlDirective (nss
, "_Items", XT
<List
<object>> (), null, AllowedMemberLocations
.Any
);
104 Key
= new XamlDirective (nss
, "Key", XT
<object> (), null, AllowedMemberLocations
.Any
);
105 Lang
= new XamlDirective (nssXml
, "lang", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
106 Members
= new XamlDirective (nss
, "Members", XT
<List
<MemberDefinition
>> (), null, AllowedMemberLocations
.MemberElement
);
107 Name
= new XamlDirective (nss
, "Name", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
108 PositionalParameters
= new XamlDirective (nss
, "_PositionalParameters", XT
<List
<object>> (), null, AllowedMemberLocations
.Any
);
109 Space
= new XamlDirective (nssXml
, "space", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
110 Subclass
= new XamlDirective (nss
, "Subclass", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
111 SynchronousMode
= new XamlDirective (nss
, "SynchronousMode", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
112 Shared
= new XamlDirective (nss
, "Shared", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
113 TypeArguments
= new XamlDirective (nss
, "TypeArguments", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
114 Uid
= new XamlDirective (nss
, "Uid", XT
<string> (), null, AllowedMemberLocations
.Attribute
);
115 UnknownContent
= new XamlDirective (nss
, "_UnknownContent", XT
<object> (), null, AllowedMemberLocations
.MemberElement
) { InternalIsUnknown = true }
;
117 AllDirectives
= new ReadOnlyCollection
<XamlDirective
> (new XamlDirective
[] {Arguments, AsyncRecords, Base, Class, ClassAttributes, ClassModifier, Code, ConnectionId, FactoryMethod, FieldModifier, Initialization, Items, Key, Lang, Members, Name, PositionalParameters, Space, Subclass, SynchronousMode, Shared, TypeArguments, Uid, UnknownContent}
);
119 InitializingDirectives
= false;
122 static readonly string [] xaml_nss
= new string [] {Xaml2006Namespace}
;
124 public static IList
<string> XamlNamespaces
{
125 get { return xaml_nss; }
128 static readonly string [] xml_nss
= new string [] {Xml1998Namespace}
;
130 public static IList
<string> XmlNamespaces
{
131 get { return xml_nss; }
134 public static ReadOnlyCollection
<XamlDirective
> AllDirectives { get; private set; }
136 public static XamlDirective Arguments { get; private set; }
137 public static XamlDirective AsyncRecords { get; private set; }
138 public static XamlDirective Base { get; private set; }
139 public static XamlDirective Class { get; private set; }
140 public static XamlDirective ClassAttributes { get; private set; }
141 public static XamlDirective ClassModifier { get; private set; }
142 public static XamlDirective Code { get; private set; }
143 public static XamlDirective ConnectionId { get; private set; }
144 public static XamlDirective FactoryMethod { get; private set; }
145 public static XamlDirective FieldModifier { get; private set; }
146 public static XamlDirective Initialization { get; private set; }
147 public static XamlDirective Items { get; private set; }
148 public static XamlDirective Key { get; private set; }
149 public static XamlDirective Lang { get; private set; }
150 public static XamlDirective Members { get; private set; }
151 public static XamlDirective Name { get; private set; }
152 public static XamlDirective PositionalParameters { get; private set; }
153 public static XamlDirective Subclass { get; private set; }
154 public static XamlDirective SynchronousMode { get; private set; }
155 public static XamlDirective Shared { get; private set; }
156 public static XamlDirective Space { get; private set; }
157 public static XamlDirective TypeArguments { get; private set; }
158 public static XamlDirective Uid { get; private set; }
159 public static XamlDirective UnknownContent { get; private set; }
161 public static ReadOnlyCollection
<XamlType
> AllTypes { get; private set; }
163 public static XamlType Array { get; private set; }
164 public static XamlType Boolean { get; private set; }
165 public static XamlType Byte { get; private set; }
166 public static XamlType Char { get; private set; }
167 public static XamlType Decimal { get; private set; }
168 public static XamlType Double { get; private set; }
169 public static XamlType Int16 { get; private set; }
170 public static XamlType Int32 { get; private set; }
171 public static XamlType Int64 { get; private set; }
172 public static XamlType Member { get; private set; }
173 public static XamlType Null { get; private set; }
174 public static XamlType Object { get; private set; }
175 public static XamlType Property { get; private set; }
176 public static XamlType Reference { get; private set; }
177 public static XamlType Single { get; private set; }
178 public static XamlType Static { get; private set; }
179 public static XamlType String { get; private set; }
180 public static XamlType TimeSpan { get; private set; }
181 public static XamlType Type { get; private set; }
182 public static XamlType Uri { get; private set; }
183 public static XamlType XData { get; private set; }
185 internal static bool IsValidXamlName (string name
)
187 if (string.IsNullOrEmpty (name
))
189 if (!IsValidXamlName (name
[0], true))
191 foreach (char c
in name
)
192 if (!IsValidXamlName (c
, false))
197 static bool IsValidXamlName (char c
, bool first
)
201 switch (char.GetUnicodeCategory (c
)) {
202 case UnicodeCategory
.LowercaseLetter
:
203 case UnicodeCategory
.UppercaseLetter
:
204 case UnicodeCategory
.TitlecaseLetter
:
205 case UnicodeCategory
.OtherLetter
:
206 case UnicodeCategory
.LetterNumber
:
208 case UnicodeCategory
.NonSpacingMark
:
209 case UnicodeCategory
.DecimalDigitNumber
:
210 case UnicodeCategory
.SpacingCombiningMark
:
211 case UnicodeCategory
.ModifierLetter
:
218 internal static XamlType
GetSpecialXaml2006Type (string name
)
220 // FIXME: I'm not really sure if these *special* names
221 // should be resolved here and there. There just does
222 // not seem to be any other appropriate places.
225 return XamlLanguage
.Array
;
227 return XamlLanguage
.Member
;
229 return XamlLanguage
.Null
;
231 return XamlLanguage
.Property
;
233 return XamlLanguage
.Static
;
235 return XamlLanguage
.Type
;
240 static readonly int clr_ns_len
= "clr-namespace:".Length
;
241 static readonly int clr_ass_len
= "assembly=".Length
;
243 internal static Type
ResolveXamlTypeName (string xmlNamespace
, string xmlLocalName
, IList
<XamlTypeName
> typeArguments
, IXamlNamespaceResolver nsResolver
)
245 string ns
= xmlNamespace
;
246 string name
= xmlLocalName
;
248 if (ns
== XamlLanguage
.Xaml2006Namespace
) {
249 var xt
= GetSpecialXaml2006Type (name
);
251 xt
= AllTypes
.FirstOrDefault (t
=> t
.Name
== xmlLocalName
);
253 throw new FormatException (string.Format ("There is no type '{0}' in XAML namespace", name
));
254 return xt
.UnderlyingType
;
256 else if (!ns
.StartsWith ("clr-namespace:", StringComparison
.Ordinal
))
257 throw new FormatException (string.Format ("Unexpected XAML namespace '{0}'", ns
));
259 Type
[] genArgs
= null;
260 if (typeArguments
!= null) {
261 var xtns
= typeArguments
;
262 genArgs
= new Type
[xtns
.Count
];
263 for (int i
= 0; i
< genArgs
.Length
; i
++) {
265 genArgs
[i
] = ResolveXamlTypeName (xtn
.Namespace
, xtn
.Name
, xtn
.TypeArguments
, nsResolver
);
269 // convert xml namespace to clr namespace and assembly
270 string [] split
= ns
.Split (';');
271 if (split
.Length
!= 2 || split
[0].Length
<= clr_ns_len
|| split
[1].Length
<= clr_ass_len
)
272 throw new XamlParseException (string.Format ("Cannot resolve runtime namespace from XML namespace '{0}'", ns
));
273 string tns
= split
[0].Substring (clr_ns_len
);
274 string aname
= split
[1].Substring (clr_ass_len
);
276 string tfn
= tns
.Length
> 0 ? tns
+ '.' + name
: name
;
278 tfn
+= "`" + genArgs
.Length
;
279 string taqn
= tfn
+ (aname
.Length
> 0 ? ", " + aname
: string.Empty
);
280 var ret
= System
.Type
.GetType (taqn
);
282 throw new XamlParseException (string.Format ("Cannot resolve runtime type from XML namespace '{0}', local name '{1}' with {2} type arguments ({3})", ns
, name
, typeArguments
.Count
, taqn
));
283 return genArgs
== null ? ret
: ret
.MakeGenericType (genArgs
);