Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorConverters/XmlXamlWriter.cs @ 13856

Last change on this file since 13856 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 33.6 KB
Line 
1using System;
2using System.IO;
3using System.Xml;
4using System.Linq;
5using System.Text;
6using System.Reflection;
7using System.Collections;
8using System.Globalization;
9using System.Collections.Generic;
10
11using System.Windows;
12using System.Windows.Markup;
13using System.Windows.Markup.Primitives;
14
15using SharpVectors.Runtime;
16using SharpVectors.Renderers;
17using SharpVectors.Renderers.Wpf;
18using SharpVectors.Renderers.Utils;
19
20namespace SharpVectors.Converters
21{
22    /// <summary>
23    /// This is a customized XAML writer, which provides Extensible Application
24    /// Markup Language (XAML) serialization of provided runtime objects into XAML.
25    /// </summary>
26    /// <remarks>
27    /// This is designed to be used by the SVG to XAML converters, and may not be
28    /// useful in general applications.
29    /// </remarks>
30    public sealed class XmlXamlWriter
31    {
32        #region Private Fields
33
34        private bool _nullExtension;
35        private Type _nullType;
36
37        private string _windowsDir;
38        private string _windowsPath;
39
40        private NamespaceCache _namespaceCache;
41        private WpfDrawingSettings _wpfSettings;
42
43        private Dictionary<Type, string> _contentProperties;
44        private Dictionary<string, NamespaceMap> _dicNamespaceMap;
45
46        #endregion
47
48        #region Constructors and Destructor
49
50        /// <overloads>
51        /// Initializes a new instance of the <see cref="XmlXamlWriter"/> class.
52        /// </overloads>
53        /// <summary>
54        /// Initializes a new instance of the <see cref="XmlXamlWriter"/> class
55        /// with the default settings.
56        /// </summary>
57        public XmlXamlWriter()
58            : this(null)
59        {
60        }
61
62        /// <summary>
63        /// Initializes a new instance of the <see cref="XmlXamlWriter"/> class
64        /// with the specified settings.
65        /// </summary>
66        /// <param name="settings">
67        /// An instance of <see cref="WpfDrawingSettings"/> specifying the
68        /// rendering options.
69        /// </param>
70        public XmlXamlWriter(WpfDrawingSettings settings)
71        {
72            _nullType          = typeof(NullExtension);
73            _namespaceCache    = new NamespaceCache();
74            _dicNamespaceMap   = new Dictionary<string, NamespaceMap>(StringComparer.OrdinalIgnoreCase);
75            _contentProperties = new Dictionary<Type, string>();
76
77            _windowsPath = "%WINDIR%";
78            _windowsDir  = Environment.ExpandEnvironmentVariables(_windowsPath).ToLower();
79
80            _windowsDir  = _windowsDir.Replace(@"\", "/");
81            _wpfSettings = settings;
82        }
83
84        #endregion
85
86        #region Public Properties
87
88        /// <summary>
89        /// Gets or sets a value indicating whether to include a null markup
90        /// extension in the output XAML.
91        /// </summary>
92        /// <value>
93        /// This is <see langword="true"/> if the null markup extension is
94        /// included in the output XAML; otherwise, it is <see langword="false"/>.
95        /// The default is <see langword="false"/>.
96        /// </value>
97        public bool IncludeNullExtension
98        {
99            get
100            {
101                return _nullExtension;
102            }
103            set
104            {
105                _nullExtension = value;
106            }
107        }
108
109        #endregion
110
111        #region Public Methods
112
113        public static string Convert(object obj)
114        {
115            XmlXamlWriter writer = new XmlXamlWriter();
116
117            return writer.Save(obj);
118        }
119
120        // Summary:
121        // Returns a Extensible Application Markup Language (XAML) string that serializes
122        // the provided object.
123        //
124        // Parameters:
125        // obj:
126        // The element to be serialized. Typically, this is the root element of a page
127        // or application.
128        //
129        // Returns:
130        // Extensible Application Markup Language (XAML) string that can be written
131        // to a stream or file. The logical tree of all elements that fall under the
132        // provided obj element will be serialized.
133        //
134        // Exceptions:
135        // System.Security.SecurityException:
136        // the application is not running in full trust.
137        //
138        // System.ArgumentNullException:
139        // obj is null.
140        public string Save(object obj)
141        {
142            if (obj == null)
143            {
144                return String.Empty;
145            }
146
147            if (_contentProperties == null)
148            {
149                _contentProperties = new Dictionary<Type, string>();
150            }
151
152            //TODO--PAUL: For now just cheat...
153            string nsName = obj.GetType().Namespace;
154
155            if (nsName != null && nsName.StartsWith("System.Windows"))
156            {
157                _namespaceCache.IsFrameworkRoot = true;
158            }
159
160            ResolveXmlNamespaces(obj);
161
162            XmlWriterSettings settings = new XmlWriterSettings();
163            settings.Indent = true;
164            settings.OmitXmlDeclaration = true;
165
166            StringBuilder builder = new StringBuilder();
167            StringWriter writer = new StringWriter(builder);
168            using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
169            {
170                WriteObject(null, obj, xmlWriter, true);
171            }
172            writer.Close();
173
174            _contentProperties = null;
175
176            return builder.ToString();
177        }
178
179        //
180        // Summary:
181        // Saves Extensible Application Markup Language (XAML) information into a provided
182        // stream to serialize the provided object.
183        //
184        // Parameters:
185        // obj:
186        // The element to be serialized. Typically, this is the root element of a page
187        // or application.
188        //
189        // stream:
190        // Destination stream for the serialized XAML information.
191        //
192        // Exceptions:
193        // System.Security.SecurityException:
194        // the application is not running in full trust.
195        //
196        // System.ArgumentNullException:
197        // obj is null -or- stream is null.
198        public void Save(object obj, Stream stream)
199        {
200            if (obj == null)
201            {
202                return;
203            }
204
205            if (_contentProperties == null)
206            {
207                _contentProperties = new Dictionary<Type, string>();
208            }
209
210            //TODO--PAUL: For now just cheat...
211            string nsName = obj.GetType().Namespace;
212
213            if (nsName != null && nsName.StartsWith("System.Windows"))
214            {
215                _namespaceCache.IsFrameworkRoot = true;
216            }
217
218            ResolveXmlNamespaces(obj);
219
220            XmlWriterSettings settings = new XmlWriterSettings();
221            settings.Indent = true;
222            settings.OmitXmlDeclaration = true;
223
224            using (XmlWriter xmlWriter = XmlWriter.Create(stream, settings))
225            {
226                WriteObject(null, obj, xmlWriter, true);
227            }
228
229            _contentProperties = null;
230        }
231
232        //
233        // Summary:
234        // Saves Extensible Application Markup Language (XAML) information as the source
235        // for a provided text writer object. The output of the text writer can then
236        // be used to serialize the provided object.
237        //
238        // Parameters:
239        // writer:
240        // TextWriter instance to use to write the serialized XAML information.
241        //
242        // obj:
243        // The element to be serialized. Typically, this is the root element of a page
244        // or application.
245        //
246        // Exceptions:
247        // System.ArgumentNullException:
248        // obj is null -or- writer is null.
249        //
250        // System.Security.SecurityException:
251        // the application is not running in full trust.
252        public void Save(object obj, TextWriter writer)
253        {
254            if (obj == null)
255            {
256                return;
257            }
258
259            if (_contentProperties == null)
260            {
261                _contentProperties = new Dictionary<Type, string>();
262            }
263
264            //TODO--PAUL: For now just cheat...
265            string nsName = obj.GetType().Namespace;
266
267            if (nsName != null && nsName.StartsWith("System.Windows"))
268            {
269                _namespaceCache.IsFrameworkRoot = true;
270            }
271
272            ResolveXmlNamespaces(obj);
273
274            XmlWriterSettings settings = new XmlWriterSettings();
275            settings.Indent = true;
276            settings.OmitXmlDeclaration = true;
277
278            using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
279            {
280                WriteObject(null, obj, xmlWriter, true);
281            }
282
283            _contentProperties = null;
284        }
285
286        //
287        // Summary:
288        // Saves Extensible Application Markup Language (XAML) information as the source
289        // for a provided XML writer object. The output of the XML writer can then be
290        // used to serialize the provided object.
291        //
292        // Parameters:
293        // obj:
294        // The element to be serialized. Typically, this is the root element of a page
295        // or application.
296        //
297        // xmlWriter:
298        // Writer to use to write the serialized XAML information.
299        //
300        // Exceptions:
301        // System.ArgumentNullException:
302        // obj is null -or- manager is null.
303        //
304        // System.Security.SecurityException:
305        // the application is not running in full trust.
306        public void Save(object obj, XmlWriter xmlWriter)
307        {
308            if (obj == null)
309            {
310                return;
311            }
312
313            if (_contentProperties == null)
314            {
315                _contentProperties = new Dictionary<Type, string>();
316            }
317
318            //TODO--PAUL: For now just cheat...
319            string nsName = obj.GetType().Namespace;
320
321            if (nsName != null && nsName.StartsWith("System.Windows"))
322            {
323                _namespaceCache.IsFrameworkRoot = true;
324            }
325
326            ResolveXmlNamespaces(obj);
327
328            WriteObject(null, obj, xmlWriter, true);
329
330            _contentProperties = null;
331        }
332
333        #endregion
334
335        #region Private Methods
336
337        private void WriteObject(object key, object obj, XmlWriter writer, bool isRoot)
338        {
339            List<MarkupProperty> propertyElements = new List<MarkupProperty>();
340            MarkupProperty contentProperty = null;
341            string contentPropertyName = null;
342            MarkupObject markupObj = MarkupWriter.GetMarkupObjectFor(obj);
343            Type objectType = markupObj.ObjectType;
344
345            string ns = _namespaceCache.GetNamespaceUriFor(objectType);
346            string prefix = _namespaceCache.GetDefaultPrefixFor(ns);
347
348            if (isRoot)
349            {
350                if (String.IsNullOrEmpty(prefix))
351                {
352                    if (String.IsNullOrEmpty(ns))
353                    {
354                        writer.WriteStartElement(markupObj.ObjectType.Name, NamespaceCache.DefaultNamespace);
355                        writer.WriteAttributeString("xmlns",
356                            NamespaceCache.XmlnsNamespace, NamespaceCache.DefaultNamespace);
357                    }
358                    else
359                    {
360                        writer.WriteStartElement(markupObj.ObjectType.Name, ns);
361                        writer.WriteAttributeString("xmlns", NamespaceCache.XmlnsNamespace, ns);
362                    }
363                }
364                else
365                {
366                    writer.WriteStartElement(prefix, markupObj.ObjectType.Name, ns);
367                }
368                writer.WriteAttributeString("xmlns", "x",
369                    NamespaceCache.XmlnsNamespace, NamespaceCache.XamlNamespace);
370
371                foreach (NamespaceMap map in _dicNamespaceMap.Values)
372                {
373                    if (!String.IsNullOrEmpty(map.Prefix) && !String.Equals(map.Prefix, "x"))
374                        writer.WriteAttributeString("xmlns", map.Prefix, NamespaceCache.XmlnsNamespace, map.XmlNamespace);
375                }
376            }
377            else
378            {
379                //TODO: Fix - the best way to handle this case...
380                if (markupObj.ObjectType.Name == "PathFigureCollection" && markupObj.Instance != null)
381                {
382                    WriteState writeState = writer.WriteState;
383
384                    if (writeState == WriteState.Element)
385                    {
386                        writer.WriteAttributeString("Figures", markupObj.Instance.ToString());
387                    }
388                    else
389                    {
390                        if (String.IsNullOrEmpty(prefix))
391                        {
392                            writer.WriteStartElement("PathGeometry.Figures");
393                        }
394                        else
395                        {
396                            writer.WriteStartElement("PathGeometry.Figures", ns);
397                        }
398                        writer.WriteString(markupObj.Instance.ToString());
399                        writer.WriteEndElement();
400                    }
401                    return;
402                }
403                else
404                {
405                    if (String.IsNullOrEmpty(prefix))
406                    {
407                        writer.WriteStartElement(markupObj.ObjectType.Name);
408                    }
409                    else
410                    {
411                        writer.WriteStartElement(markupObj.ObjectType.Name, ns);
412                    }
413                }
414            }
415
416            // Add the x:Name for object like Geometry/Drawing not derived from FrameworkElement...
417            DependencyObject dep = obj as DependencyObject;
418            if (dep != null)
419            {
420                string nameValue = dep.GetValue(FrameworkElement.NameProperty) as string;
421                if (!String.IsNullOrEmpty(nameValue) && !(dep is FrameworkElement))
422                {
423                    writer.WriteAttributeString("x", "Name", NamespaceCache.XamlNamespace, nameValue);
424                }
425            }
426
427            if (key != null)
428            {
429                string keyString = key.ToString();
430                if (keyString.Length > 0)
431                {
432                    writer.WriteAttributeString("x", "Key", NamespaceCache.XamlNamespace, keyString);
433                }
434                else
435                {
436                    //TODO: key may not be a string, what about x:Type...
437                    throw new NotImplementedException(
438                        "Sample XamlWriter cannot yet handle keys that aren't strings");
439                }
440            }
441
442            //Look for CPA info in our cache that keeps contentProperty names per Type
443            //If it doesn't have an entry, go get the info and store it.
444            if (!_contentProperties.ContainsKey(objectType))
445            {
446                string lookedUpContentProperty = String.Empty;
447                foreach (Attribute attr in markupObj.Attributes)
448                {
449                    ContentPropertyAttribute cpa = attr as ContentPropertyAttribute;
450                    if (cpa != null)
451                    {
452                        lookedUpContentProperty = cpa.Name;
453                        //Once content property is found, come out of the loop.
454                        break;
455                    }
456                }
457
458                _contentProperties.Add(objectType, lookedUpContentProperty);
459            }
460
461            contentPropertyName = _contentProperties[objectType];
462            string contentString = String.Empty;
463
464            foreach (MarkupProperty markupProperty in markupObj.Properties)
465            {
466                if (markupProperty.Name != contentPropertyName)
467                {
468                    if (markupProperty.IsValueAsString)
469                    {
470                        contentString = markupProperty.Value as string;
471                    }
472                    else if (!markupProperty.IsComposite)
473                    {
474                        string temp = markupProperty.StringValue;
475
476                        if (markupProperty.IsAttached)
477                        {
478                            string ns1 = _namespaceCache.GetNamespaceUriFor(markupProperty.DependencyProperty.OwnerType);
479                            string prefix1 = _namespaceCache.GetDefaultPrefixFor(ns1);
480
481                            if (String.IsNullOrEmpty(prefix1))
482                            {
483                                writer.WriteAttributeString(markupProperty.Name, temp);
484                            }
485                            else
486                            {
487                                writer.WriteAttributeString(markupProperty.Name, ns1, temp);
488                            }
489                        }
490                        else
491                        {
492                            if (markupProperty.Name == "FontUri" &&
493                                (_wpfSettings != null && _wpfSettings.IncludeRuntime))
494                            {
495                                string fontUri = temp.ToLower();
496                                fontUri = fontUri.Replace(_windowsDir, _windowsPath);
497
498                                StringBuilder builder = new StringBuilder();
499                                builder.Append("{");
500                                builder.Append("svg");
501                                builder.Append(":");
502                                builder.Append("SvgFontUri ");
503                                builder.Append(fontUri);
504                                builder.Append("}");
505
506                                writer.WriteAttributeString(markupProperty.Name, builder.ToString());
507                            }
508                            else
509                            {
510                                writer.WriteAttributeString(markupProperty.Name, temp);
511                            }
512                        }
513                    }
514                    else if (markupProperty.Value.GetType() == _nullType)
515                    {
516                        if (_nullExtension)
517                        {
518                            writer.WriteAttributeString(markupProperty.Name, "{x:Null}");
519                        }
520                    }
521                    else
522                    {
523                        propertyElements.Add(markupProperty);
524                    }
525                }
526                else
527                {
528                    contentProperty = markupProperty;
529                }
530            }
531
532            if (contentProperty != null || propertyElements.Count > 0 || contentString != String.Empty)
533            {
534                foreach (MarkupProperty markupProp in propertyElements)
535                {
536                    string ns2 = _namespaceCache.GetNamespaceUriFor(markupObj.ObjectType);
537                    string prefix2 = null;
538                    if (!String.IsNullOrEmpty(ns2))
539                    {
540                        prefix2 = _namespaceCache.GetDefaultPrefixFor(ns2);
541                    }
542
543                    string propElementName = markupObj.ObjectType.Name + "." + markupProp.Name;
544                    if (String.IsNullOrEmpty(prefix2))
545                    {
546                        writer.WriteStartElement(propElementName);
547                    }
548                    else
549                    {
550                        writer.WriteStartElement(prefix2, propElementName, ns2);
551                    }
552
553                    WriteChildren(writer, markupProp);
554                    writer.WriteEndElement();
555                }
556
557                if (contentString != String.Empty)
558                {
559                    writer.WriteValue(contentString);
560                }
561                else if (contentProperty != null)
562                {
563                    if (contentProperty.Value is string)
564                    {
565                        writer.WriteValue(contentProperty.StringValue);
566                    }
567                    else
568                    {
569                        WriteChildren(writer, contentProperty);
570                    }
571                }
572            }
573            writer.WriteEndElement();
574        }
575
576        private void WriteChildren(XmlWriter writer, MarkupProperty markupProp)
577        {
578            if (!markupProp.IsComposite)
579            {
580                WriteObject(null, markupProp.Value, writer, false);
581            }
582            else
583            {
584                IList collection = markupProp.Value as IList;
585                IDictionary dictionary = markupProp.Value as IDictionary;
586                if (collection != null)
587                {
588                    foreach (object obj in collection)
589                    {
590                        WriteObject(null, obj, writer, false);
591                    }
592                }
593                else if (dictionary != null)
594                {
595                    foreach (object key in dictionary.Keys)
596                    {
597                        WriteObject(key, dictionary[key], writer, false);
598                    }
599                }
600                else
601                {
602                    WriteObject(null, markupProp.Value, writer, false);
603                }
604            }
605        }
606
607        private void ResolveXmlNamespaces(object obj)
608        {
609            List<MarkupProperty> propertyElements = new List<MarkupProperty>();
610            MarkupProperty contentProperty = null;
611            string contentPropertyName = null;
612            MarkupObject markupObj = MarkupWriter.GetMarkupObjectFor(obj);
613            Type objectType = markupObj.ObjectType;
614
615            string ns = _namespaceCache.GetNamespaceUriFor(objectType);
616            if (!String.IsNullOrEmpty(ns))
617            {
618                string prefix = _namespaceCache.GetDefaultPrefixFor(ns);
619                _dicNamespaceMap[ns] = new NamespaceMap(prefix, ns);
620            }
621
622            //Look for CPA info in our cache that keeps contentProperty names per Type
623            //If it doesn't have an entry, go get the info and store it.
624            if (!_contentProperties.ContainsKey(objectType))
625            {
626                string lookedUpContentProperty = String.Empty;
627
628                foreach (Attribute attr in markupObj.Attributes)
629                {
630                    ContentPropertyAttribute cpa = attr as ContentPropertyAttribute;
631                    if (cpa != null)
632                    {
633                        lookedUpContentProperty = cpa.Name;
634                        //Once content property is found, come out of the loop.
635                        break;
636                    }
637                }
638
639                _contentProperties.Add(objectType, lookedUpContentProperty);
640            }
641
642            contentPropertyName = _contentProperties[objectType];
643
644            string contentString = String.Empty;
645
646            foreach (MarkupProperty markupProperty in markupObj.Properties)
647            {
648                if (markupProperty.Name != contentPropertyName)
649                {
650                    if (markupProperty.IsValueAsString)
651                    {
652                        contentString = markupProperty.Value as string;
653                    }
654                    else if (!markupProperty.IsComposite)
655                    {
656                        //Bug Fix DX-0120123
657                        if (markupProperty.DependencyProperty != null)
658                        {
659                            string ns1 = _namespaceCache.GetNamespaceUriFor(
660                                markupProperty.DependencyProperty.OwnerType);
661                            string prefix1 = _namespaceCache.GetDefaultPrefixFor(ns1);
662
663                            if (!String.IsNullOrEmpty(prefix1))
664                            {
665                                _dicNamespaceMap[ns1] = new NamespaceMap(prefix1, ns1);
666                            }
667                        }
668                    }
669                    else if (markupProperty.Value.GetType() == _nullType)
670                    {
671                    }
672                    else
673                    {
674                        propertyElements.Add(markupProperty);
675                    }
676                }
677                else
678                {
679                    contentProperty = markupProperty;
680                }
681            }
682
683            if (contentProperty != null || propertyElements.Count > 0 || contentString != String.Empty)
684            {
685                foreach (MarkupProperty markupProp in propertyElements)
686                {
687                    string ns2 = _namespaceCache.GetNamespaceUriFor(markupObj.ObjectType);
688                    if (!String.IsNullOrEmpty(ns2))
689                    {
690                        string prefix2 = _namespaceCache.GetDefaultPrefixFor(ns2);
691                        _dicNamespaceMap[ns2] = new NamespaceMap(prefix2, ns2);
692                    }
693                    ResolveChildXmlNamespaces(markupProp);
694                }
695
696                if (contentProperty != null)
697                {
698                    if (!(contentProperty.Value is String))
699                    {
700                        ResolveChildXmlNamespaces(contentProperty);
701                    }
702                }
703            }
704        }
705
706        private void ResolveChildXmlNamespaces(MarkupProperty markupProp)
707        {
708            if (!markupProp.IsComposite)
709            {
710                ResolveXmlNamespaces(markupProp);
711            }
712            else
713            {
714                IList collection = markupProp.Value as IList;
715                IDictionary dictionary = markupProp.Value as IDictionary;
716                if (collection != null)
717                {
718                    foreach (object obj in collection)
719                    {
720                        ResolveXmlNamespaces(obj);
721                    }
722                }
723                else if (dictionary != null)
724                {
725                    foreach (object key in dictionary.Keys)
726                    {
727                        ResolveXmlNamespaces(dictionary[key]);
728                    }
729                }
730                else
731                {
732                    ResolveXmlNamespaces(markupProp.Value);
733                }
734            }
735        }
736
737        #endregion
738
739        #region NamespaceCache Class
740
741        private sealed class NamespaceCache
742        {
743            public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
744            public const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
745            public const string DefaultNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
746            public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
747
748            public const string ClrNamespace = "clr-namespace:";
749
750            private bool _isFrameworkRoot;
751            private Dictionary<string, string> _defaultPrefixes;
752            private Dictionary<Assembly, Dictionary<string, string>> _xmlnsDefinitions;
753
754            public NamespaceCache()
755            {
756                _defaultPrefixes = new Dictionary<string, string>();
757                _xmlnsDefinitions = new Dictionary<Assembly, Dictionary<string, string>>();
758            }
759
760            public bool IsFrameworkRoot
761            {
762                get
763                {
764                    return _isFrameworkRoot;
765                }
766                set
767                {
768                    _isFrameworkRoot = value;
769                }
770            }
771
772            public string GetDefaultPrefixFor(string uri)
773            {
774                string uriPrefix;
775                _defaultPrefixes.TryGetValue(uri, out uriPrefix);
776                if (uriPrefix != null)
777                {
778                    return uriPrefix;
779                }
780                uriPrefix = "assembly";
781                if (!uri.StartsWith(ClrNamespace, StringComparison.OrdinalIgnoreCase))
782                {
783                    return uriPrefix;
784                }
785                string assNamespace = uri.Substring(ClrNamespace.Length, uri.IndexOf(";",
786                    StringComparison.OrdinalIgnoreCase) - ClrNamespace.Length);
787                if (!String.IsNullOrEmpty(assNamespace))
788                {
789                    StringBuilder builder = new StringBuilder();
790                    for (int i = 0; i < assNamespace.Length; i++)
791                    {
792                        char ch = assNamespace[i];
793                        if ((ch >= 'A') && (ch <= 'Z'))
794                        {
795                            builder.Append(ch.ToString().ToLower());
796                        }
797                    }
798                    if (builder.Length > 0)
799                    {
800                        uriPrefix = builder.ToString();
801                    }
802                }
803
804                return uriPrefix;
805            }
806
807            public string GetNamespaceUriFor(Type type)
808            {
809                string typeNamespace = String.Empty;
810                if (type.Namespace == null)
811                {
812                    return String.Format(CultureInfo.InvariantCulture, "clr-namespace:;assembly={0}",
813                        new object[] { type.Assembly.GetName().Name });
814                }
815                if (!GetMappingsFor(type.Assembly).TryGetValue(type.Namespace, out typeNamespace))
816                {
817                    if (!String.Equals(type.Namespace, "System.Windows.Markup.Primitives"))
818                    {
819                        typeNamespace = String.Format(CultureInfo.InvariantCulture,
820                            "clr-namespace:{0};assembly={1}", new object[] { type.Namespace,
821                                type.Assembly.GetName().Name });
822                    }
823                }
824
825                return typeNamespace;
826            }
827
828            public static string GetAssemblyNameFromType(Type type)
829            {
830                string[] names = type.Assembly.FullName.Split(',');
831                if (names.Length > 0)
832                {
833                    return names[0];
834                }
835
836                return String.Empty;
837            }
838
839            private Dictionary<string, string> GetMappingsFor(Assembly assembly)
840            {
841                Dictionary<string, string> dictionary;
842                if (_xmlnsDefinitions.TryGetValue(assembly, out dictionary))
843                {
844                    return dictionary;
845                }
846                foreach (XmlnsPrefixAttribute attribute in assembly.GetCustomAttributes(
847                    typeof(XmlnsPrefixAttribute), true))
848                {
849                    _defaultPrefixes[attribute.XmlNamespace] = attribute.Prefix;
850                }
851                //TODO--PAUL: For now just cheat...
852                if (_isFrameworkRoot)
853                {
854                    _defaultPrefixes[DefaultNamespace] = String.Empty;
855                }
856
857                dictionary = new Dictionary<string, string>();
858                _xmlnsDefinitions[assembly] = dictionary;
859                foreach (XmlnsDefinitionAttribute attribute in assembly.GetCustomAttributes(
860                    typeof(XmlnsDefinitionAttribute), true))
861                {
862                    if (attribute.AssemblyName == null)
863                    {
864                        string prefix1 = null;
865                        string prefix2 = null;
866                        string prefix3 = null;
867                        if (dictionary.TryGetValue(attribute.ClrNamespace, out prefix1) &&
868                            _defaultPrefixes.TryGetValue(prefix1, out prefix2))
869                        {
870                            _defaultPrefixes.TryGetValue(attribute.XmlNamespace, out prefix3);
871                        }
872                        if (((prefix1 == null) || (prefix2 == null)) ||
873                            ((prefix3 != null) && (prefix2.Length > prefix3.Length)))
874                        {
875                            dictionary[attribute.ClrNamespace] = attribute.XmlNamespace;
876                        }
877                    }
878                    else
879                    {
880                        Assembly nextAssembly = Assembly.Load(new AssemblyName(attribute.AssemblyName));
881                        if (nextAssembly != null)
882                        {
883                            GetMappingsFor(nextAssembly)[attribute.ClrNamespace] = attribute.XmlNamespace;
884                        }
885                    }
886                }
887
888                return dictionary;
889            }
890        }
891
892        #endregion
893
894        #region NamespaceMap Class
895
896        private sealed class NamespaceMap
897        {
898            private string _prefix;
899            private string _xmlNamespace;
900
901            public NamespaceMap(string prefix, string xmlNamespace)
902            {
903                _prefix = prefix;
904                _xmlNamespace = xmlNamespace;
905            }
906
907            public string Prefix
908            {
909                get
910                {
911                    return _prefix;
912                }
913                set
914                {
915                    _prefix = value;
916                }
917            }
918
919            public string XmlNamespace
920            {
921                get
922                {
923                    return _xmlNamespace;
924                }
925                set
926                {
927                    _xmlNamespace = value;
928                }
929            }
930        }
931
932        #endregion
933    }
934}
Note: See TracBrowser for help on using the repository browser.