2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / class / System.Windows / Mono / ManagedXamlLoader.cs
blob6500379af64c6082f6be5d93030723c8b457ba2a
1 //
2 // ManagedXamlLoader.cs
3 //
4 // Contact:
5 // Moonlight List (moonlight-list@lists.ximian.com)
6 //
7 // Copyright 2007 Novell, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Diagnostics;
32 using System.Reflection;
33 using System.Collections.Generic;
34 using System.IO;
35 using System.Windows;
36 using System.Windows.Controls;
37 using System.Windows.Markup;
38 using System.Runtime.InteropServices;
39 using System.ComponentModel;
40 using System.Windows.Data;
41 using System.Text.RegularExpressions;
42 using Mono;
44 namespace Mono.Xaml
46 internal sealed class ManagedXamlLoader : XamlLoader {
48 Assembly assembly;
49 XamlLoaderCallbacks callbacks;
50 GCHandle handle;
52 public ManagedXamlLoader ()
56 public ManagedXamlLoader (Assembly assembly, string resourceBase, IntPtr surface, IntPtr plugin) : base (resourceBase, surface, plugin)
58 this.assembly = assembly;
61 public override void Setup (IntPtr native_loader, IntPtr plugin, IntPtr surface, string filename, string contents)
63 base.Setup (native_loader, plugin, surface, filename, contents);
66 // Registers callbacks that are invoked from the
67 // unmanaged code.
69 unsafe {
70 callbacks.lookup_object = new LookupObjectCallback (cb_lookup_object);
71 callbacks.create_gchandle = new CreateGCHandleCallback (cb_create_gchandle);
72 callbacks.set_property = new SetPropertyCallback (cb_set_property);
73 callbacks.import_xaml_xmlns = new ImportXamlNamespaceCallback (cb_import_xaml_xmlns);
74 callbacks.get_content_property_name = new GetContentPropertyNameCallback (cb_get_content_property_name);
75 callbacks.add_child = new AddChildCallback (cb_add_child);
78 NativeMethods.xaml_loader_set_callbacks (native_loader, callbacks);
80 if (plugin != IntPtr.Zero)
81 System.Windows.Interop.PluginHost.SetPluginHandle (plugin);
83 if (!AllowMultipleSurfacesPerDomain) {
84 PluginInDomain = plugin;
85 SurfaceInDomain = surface;
89 //
90 // Creates a managed dependency object from the xaml.
92 public override object CreateObjectFromString (string xaml, bool createNamescope)
94 return CreateObjectFromString (xaml, createNamescope, false);
97 public override object CreateObjectFromString (string xaml, bool createNamescope, bool validateTemplates)
99 if (xaml == null)
100 throw new ArgumentNullException ("xaml");
102 IntPtr top;
103 object result;
104 Kind kind;
106 DependencyObject.Initialize ();
108 top = CreateFromString (xaml, createNamescope, validateTemplates, out kind);
110 if (top == IntPtr.Zero)
111 return null;
113 result = Value.ToObject (null, top);
114 DependencyObject dob = result as DependencyObject;
115 if (dob != null) {
116 NativeMethods.event_object_unref (dob.native);
119 return result;
123 // Creates a managed dependency object from the xaml in the file
125 public override object CreateObjectFromFile (string file, bool createNamescope)
127 if (file == null)
128 throw new ArgumentNullException ("file");
130 IntPtr top;
131 object result;
132 Kind kind;
134 DependencyObject.Initialize ();
136 top = CreateFromFile (file, createNamescope, out kind);
138 if (top == IntPtr.Zero)
139 return null;
141 result = Value.ToObject (null, top);
142 DependencyObject dob = result as DependencyObject;
143 if (dob != null) {
144 NativeMethods.event_object_unref (dob.native);
147 return result;
151 // Tries to load the assembly.
153 public AssemblyLoadResult LoadAssembly (string asm_name, out Assembly clientlib)
155 clientlib = null;
157 clientlib = Application.GetAssembly (asm_name);
158 return clientlib != null ? AssemblyLoadResult.Success : AssemblyLoadResult.MissingAssembly;
161 private unsafe bool TryGetDefaultAssemblyName (Value* top_level, out string assembly_name)
163 if (assembly != null) {
164 assembly_name = assembly.GetName ().Name;
165 return true;
168 object obj = Value.ToObject (null, top_level);
170 if (obj == null) {
171 assembly_name = null;
172 return false;
175 assembly_name = obj.GetType ().Assembly.GetName ().Name;
176 return true;
179 private unsafe bool LookupObject (Value *top_level, Value *parent, string xmlns, string name, bool create, bool is_property, out Value value)
181 if (name == null)
182 throw new ArgumentNullException ("type_name");
185 if (is_property) {
186 int dot = name.IndexOf ('.');
187 return LookupPropertyObject (top_level, parent, xmlns, name, dot, create, out value);
190 if (top_level == null && xmlns == null) {
191 return LookupComponentFromName (top_level, name, create, out value);
194 string assembly_name = AssemblyNameFromXmlns (xmlns);
195 string clr_namespace = ClrNamespaceFromXmlns (xmlns);
196 string full_name = string.IsNullOrEmpty (clr_namespace) ? name : clr_namespace + "." + name;
198 Type type = LookupType (top_level, assembly_name, full_name);
199 if (type == null) {
200 Console.Error.WriteLine ("ManagedXamlLoader::LookupObject: GetType ({0}) failed using assembly: {1} ({2}, {3}).", name, assembly_name, xmlns, full_name);
201 value = Value.Empty;
202 return false;
205 if (create) {
207 if (!type.IsPublic) {
208 value = Value.Empty;
209 throw new XamlParseException ("Attempting to create a private type");
212 object res = null;
213 try {
214 res = Activator.CreateInstance (type);
215 } catch (TargetInvocationException ex) {
216 Console.WriteLine (ex);
217 Console.Error.WriteLine ("ManagedXamlLoader::LookupObject: CreateInstance ({0}) failed: {1}", name, ex.InnerException);
218 value = Value.Empty;
219 return false;
222 if (res == null) {
223 Console.Error.WriteLine ("ManagedXamlLoader::LookupObject ({0}, {1}, {2}): unable to create object instance: '{3}', the object was of type '{4}'",
224 assembly_name, xmlns, name, full_name, type.FullName);
225 value = Value.Empty;
226 return false;
228 value = Value.FromObject (res, false);
229 } else {
230 value = Value.Empty;
231 value.k = Deployment.Current.Types.Find (type).native_handle;
234 return true;
237 private unsafe bool LookupPropertyObject (Value* top_level, Value* parent_value, string xmlns, string name, int dot, bool create, out Value value)
239 string prop_name = name.Substring (dot + 1);
240 object parent = Value.ToObject (null, parent_value);
242 if (parent == null) {
243 value = Value.Empty;
244 return false;
247 PropertyInfo pi = null;
248 bool is_attached = true;
249 string type_name = name.Substring (0, dot);
251 Type t = parent.GetType ();
252 while (t != typeof (object)) {
253 if (t.Name == type_name) {
254 is_attached = false;
255 break;
257 t = t.BaseType;
260 if (is_attached) {
261 string full_type_name = type_name;
262 if (xmlns != null) {
263 string ns = ClrNamespaceFromXmlns (xmlns);
264 full_type_name = String.Concat (ns, ".", type_name);
267 MethodInfo set_method = GetSetMethodForAttachedProperty (top_level, xmlns, type_name, full_type_name, prop_name);
269 ParameterInfo [] set_params = set_method.GetParameters ();
270 if (set_params == null || set_params.Length < 2) {
271 value = Value.Empty;
272 Console.Error.WriteLine ("set method signature is incorrect.");
273 return false;
276 ManagedType mt = Deployment.Current.Types.Find (set_params [1].ParameterType);
277 value = Value.Empty;
278 value.IsNull = true;
279 value.k = mt.native_handle;
280 return true;
281 } else {
283 pi = parent.GetType ().GetProperty (name.Substring (dot + 1), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
285 if (pi == null) {
286 value = Value.Empty;
287 return false;
290 ManagedType mt = Deployment.Current.Types.Find (pi.PropertyType);
291 value = Value.Empty;
292 value.k = mt.native_handle;
293 value.IsNull = true;
295 return true;
299 private unsafe bool LookupComponentFromName (Value* top_level, string name, bool create, out Value value)
301 if (!create) {
302 Type type = Application.GetComponentTypeFromName (name);
303 if (type == null) {
304 value = Value.Empty;
305 return false;
307 value = Value.Empty;
308 value.k = Deployment.Current.Types.Find (type).native_handle;
309 return true;
312 object obj = Application.CreateComponentFromName (name);
313 if (obj == null) {
314 value = Value.Empty;
315 return false;
318 value = Value.FromObject (obj, false);
319 return true;
322 private static bool IsAttachedProperty (string name)
324 return name.IndexOf ('.') > 0;
327 private unsafe bool IsAttachedProperty (XamlCallbackData *data, object target, string xmlns, string prop_xmlns, string name)
329 string type_name = null;
330 string full_type_name = null;
332 name = GetNameForAttachedProperty (xmlns, prop_xmlns, name, out type_name, out full_type_name);
334 if (name == null)
335 return false;
337 MethodInfo set_method = GetSetMethodForAttachedProperty (data->top_level, prop_xmlns, type_name, full_type_name, name);
338 if (set_method == null)
339 return false;
341 return !target.GetType ().IsSubclassOf (set_method.DeclaringType);
344 private unsafe DependencyProperty LookupDependencyPropertyForBinding (XamlCallbackData *data, FrameworkElement fwe, string type_name, string propertyName)
346 // map the property name + type_name to an actual DependencyProperty
347 Kind kind;
348 Type type = string.IsNullOrEmpty (type_name) ? null : TypeFromString (data, type_name);
349 if (type != null) {
350 Types.Ensure (type);
351 kind = Deployment.Current.Types.TypeToNativeKind (type);
352 } else {
353 kind = fwe.GetKind ();
356 if (kind == Kind.INVALID)
357 return null;
359 try {
360 return DependencyProperty.Lookup (kind, propertyName);
362 catch {
363 return null;
368 private unsafe bool TrySetExpression (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, Value* target_parent_ptr, string type_name, string prop_xmlns, string name, string full_name, Value* value_ptr, IntPtr value_data)
370 FrameworkElement dob = target as FrameworkElement;
371 object obj_value = Value.ToObject (null, value_ptr);
372 string str_value = obj_value as string;
374 if (str_value == null)
375 return false;
377 if (!str_value.StartsWith ("{"))
378 return false;
380 MarkupExpressionParser p = new MarkupExpressionParser (target, name, data->parser, target_data);
381 string expression = str_value;
382 object o = p.ParseExpression (ref expression);
384 if (o == null)
385 return false;
388 if (o is Binding) {
389 Binding binding = o as Binding;
390 DependencyProperty prop = null;
392 if (dob != null) {
393 string full_type_name = type_name;
394 if (IsAttachedProperty (full_name))
395 GetNameForAttachedProperty (xmlns, prop_xmlns, full_name, out type_name, out full_type_name);
396 prop = LookupDependencyPropertyForBinding (data, dob, full_type_name, name);
399 if (prop == null)
400 return false;
402 dob.SetBinding (prop, binding);
403 return true;
405 else if (o is TemplateBindingExpression) {
406 // Applying a {TemplateBinding} to a DO which is not a FrameworkElement should silently discard
407 // the binding.
408 if (dob == null)
409 return true;
411 TemplateBindingExpression tb = o as TemplateBindingExpression;
413 IntPtr context = NativeMethods.xaml_loader_get_context (data->loader);
414 IntPtr source_ptr = NativeMethods.xaml_context_get_template_binding_source (context);
416 DependencyObject templateSourceObject = NativeDependencyObjectHelper.FromIntPtr (source_ptr) as DependencyObject;
418 if (templateSourceObject == null)
419 return false;
421 DependencyProperty sourceProperty = DependencyProperty.Lookup (templateSourceObject.GetKind(),
422 tb.SourcePropertyName);
423 if (sourceProperty == null)
424 return false;
426 DependencyProperty prop = null;
428 if (dob != null)
429 prop = LookupDependencyPropertyForBinding (data, dob, type_name, name);
431 if (prop == null)
432 return false;
434 tb.TargetProperty = prop;
435 tb.Source = templateSourceObject as Control;
436 tb.SourceProperty = sourceProperty;
438 dob.SetTemplateBinding (prop, tb);
440 return true;
442 else {
443 // static resources fall into this
445 if (dob != null) {
446 DependencyProperty prop = LookupDependencyPropertyForBinding (data, dob, type_name, name);
447 if (prop == null)
448 return false;
450 o = ConvertType (null, prop.PropertyType, o);
451 dob.SetValue (prop, o);
452 } else {
453 if (IsAttachedProperty (full_name))
454 return TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, o);
456 PropertyInfo pi = target.GetType ().GetProperty (name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
458 o = ConvertType (null, pi.PropertyType, o);
459 SetValue (data, target_data, pi, target, o);
460 return true;
464 return true;
467 private string GetNameForAttachedProperty (string xmlns, string prop_xmlns, string name, out string type_name, out string full_type_name)
469 int dot = name.IndexOf ('.');
471 if (dot >= 0) {
472 type_name = name.Substring (0, dot);
473 full_type_name = type_name;
474 if (prop_xmlns != null || xmlns != null) {
475 string ns = ClrNamespaceFromXmlns (prop_xmlns == null ? xmlns : prop_xmlns);
476 if (ns != null)
477 full_type_name = String.Concat (ns, ".", type_name);
479 name = name.Substring (++dot, name.Length - dot);
480 } else {
481 full_type_name = null;
482 type_name = null;
483 return null;
486 return name;
489 private unsafe bool TrySetAttachedProperty (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, string prop_xmlns, string name, Value* value_ptr)
491 string full_name = name;
492 string type_name = null;
493 string full_type_name = null;
495 name = GetNameForAttachedProperty (xmlns, prop_xmlns, name, out type_name, out full_type_name);
497 if (name == null)
498 return false;
500 string error = null;
501 object o_value = GetObjectValue (target, target_data, name, data->parser, value_ptr, out error);
503 return TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, o_value);
506 private unsafe bool TrySetAttachedProperty (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, string prop_xmlns, string name, object o_value)
508 string type_name = null;
509 string full_type_name = null;
511 name = GetNameForAttachedProperty (xmlns, prop_xmlns, name, out type_name, out full_type_name);
513 if (name == null)
514 return false;
516 MethodInfo set_method = GetSetMethodForAttachedProperty (data->top_level, prop_xmlns, type_name, full_type_name, name);
517 if (set_method == null) {
518 Console.Error.WriteLine ("set method is null: {0} {1}", String.Concat ("Set", name), prop_xmlns);
519 return false;
522 ParameterInfo [] set_params = set_method.GetParameters ();
523 if (set_params == null || set_params.Length < 2) {
524 Console.Error.WriteLine ("set method signature is incorrect.");
525 return false;
528 MethodInfo get_method = set_method.DeclaringType.GetMethod (String.Concat ("Get", name), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
531 // The Setter might actually want a collection, in this case we grab the old collection with the getter
532 // and then add the new object to the collection
534 // TODO: Check if the setter method still gets called on Silverlight
535 if (typeof (IList).IsAssignableFrom (set_params [1].ParameterType) && !(o_value is IList)) {
537 if (get_method != null || get_method.GetParameters () == null || get_method.GetParameters ().Length != 1) {
538 IList the_list = (IList) get_method.Invoke (null, new object [] { target });
540 if (the_list == null) {
541 the_list = (IList) Activator.CreateInstance (set_params [1].ParameterType);
542 if (the_list == null)
543 return false;
544 set_method.Invoke (null, new object [] {target, the_list});
547 try {
548 the_list.Add (o_value);
550 if (o_value is DependencyObject && target is DependencyObject && !(the_list is DependencyObject)) {
551 NativeMethods.dependency_object_set_parent_safe (((DependencyObject)o_value).native, ((DependencyObject)target).native);
554 return true;
556 catch {
557 // don't return here, fall through to the ConvertType case below.
559 } else {
560 // I guess we need to wrap the current value in a collection, or does this error out?
561 Console.WriteLine ("ow god my eye!");
562 return false;
566 o_value = ConvertType (get_method, set_params [1].ParameterType, o_value);
567 set_method.Invoke (null, new object [] {target, o_value});
568 return true;
571 private unsafe bool TrySetPropertyReflection (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, Value* target_parent_ptr, string type_name, string name, Value* value_ptr, IntPtr value_data, out string error)
573 PropertyInfo pi = target.GetType ().GetProperty (name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
575 if (pi == null) {
576 error = "Property does not exist.";
577 return false;
580 if (!SetPropertyFromValue (data, target, target_data, target_parent_ptr, pi, value_ptr, value_data, out error))
581 return false;
583 error = null;
584 return true;
587 private unsafe bool TrySetEventReflection (XamlCallbackData *data, string xmlns, object publisher, string type_name, string name, Value* value_ptr, out string error)
589 object subscriber = null;
590 EventInfo ie = publisher.GetType ().GetEvent (name);
591 string handler_name = Value.ToObject (null, value_ptr) as string;
593 try {
594 subscriber = Value.ToObject (null, data->top_level);
595 } catch {
599 //Console.WriteLine ("TrySetEventReflection ({0}, {1}, {2}, {3}, {4}, {5}) handler_name: {6}", data->top_level, xmlns, publisher, type_name, name, value_ptr, handler_name);
601 if (ie == null) {
602 error = "Event does not exist.";
603 return false;
607 if (handler_name == null) {
608 error = "No method name supplied for event handler.";
609 return false;
612 MethodInfo invoker_info = ie.EventHandlerType.GetMethod ("Invoke");
613 ParameterInfo [] event_params = invoker_info.GetParameters ();
615 Delegate d = null;
616 Type stype = subscriber.GetType ();
617 MethodInfo [] methods = stype.GetMethods (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance);
618 MethodInfo candidate = null;
619 bool name_match = false;
621 for (int i = 0; i < methods.Length; i++) {
622 MethodInfo m = methods [i];
623 ParameterInfo [] parameters;
625 if (m.Name != handler_name)
626 continue;
628 if (name_match) {
629 error = "Multiple candidates with the same name found for event handler.";
630 // Console.WriteLine (error);
631 return false;
634 name_match = true;
636 if (m.ReturnType != typeof (void))
637 continue;
639 parameters = m.GetParameters ();
641 if (parameters.Length != event_params.Length)
642 continue;
644 bool match = true;
645 for (int p = 0; p < parameters.Length; p++) {
646 if (!event_params [p].ParameterType.IsSubclassOf (parameters [p].ParameterType) && parameters [p].ParameterType != event_params [p].ParameterType) {
647 Console.WriteLine ("mismatch: {0} and {1}", parameters [p].ParameterType, event_params [p].ParameterType);
648 match = false;
649 break;
653 if (!match)
654 continue;
656 if (candidate != null) {
657 error = "Multiple candidates for event handler found.";
658 // Console.WriteLine (error);
659 return false;
662 candidate = m;
665 if (candidate == null) {
666 error = "Event handler not found.";
667 // Console.WriteLine (error);
668 return false;
671 d = Delegate.CreateDelegate (ie.EventHandlerType, subscriber, candidate, false);
673 if (d == null) {
674 Console.Error.WriteLine ("ManagedXamlLoader::HookupEvent ({0}, {1}, {2}): unable to create delegate (src={3} target={4}).", (IntPtr) data->top_level, name, (IntPtr)value_ptr, ie.EventHandlerType, publisher);
675 error = "Can not create even delegate.";
676 return false;
679 // Console.Error.WriteLine ("ManagedXamlLoader::HookupEvent ({0}, {1}, {2}): Successfully created delegate (src={3} target={4}).", (IntPtr) data->top_level, name, value_ptr, ie.EventHandlerType, publisher);
681 error = null;
682 ie.AddEventHandler (publisher, d);
683 return true;
686 private unsafe bool TrySetEnumContentProperty (XamlCallbackData *data, string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data)
688 object obj_value = Value.ToObject (null, value_ptr);
689 string str_value = obj_value as string;
691 if (str_value == null)
692 return false;
694 string assembly_name = AssemblyNameFromXmlns (xmlns);
695 string clr_namespace = ClrNamespaceFromXmlns (xmlns);
696 string type_name = NativeMethods.xaml_get_element_name (data->parser, target_data);
697 string full_name = String.IsNullOrEmpty (clr_namespace) ? type_name : clr_namespace + "." + type_name;
699 Type type = LookupType (data->top_level, assembly_name, full_name);
701 if (type == null || !type.IsEnum)
702 return false;
704 object e = Enum.Parse (type, str_value, true);
706 NativeMethods.value_free_value2 ((IntPtr)target_ptr);
708 unsafe {
709 Value *val = (Value *) target_ptr;
711 GCHandle handle = GCHandle.Alloc (e);
712 val->k = Kind.MANAGED;
713 val->u.p = GCHandle.ToIntPtr (handle);
716 return true;
719 private unsafe bool TrySetCollectionContentProperty (string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data)
721 IList list = target as IList;
723 if (list == null)
724 return false;
726 object value = Value.ToObject (null, value_ptr);
728 list.Add (value);
729 return true;
732 private unsafe bool TrySetObjectTextProperty (XamlCallbackData *data, string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data)
734 object obj_value = Value.ToObject (null, value_ptr);
735 string str_value = obj_value as string;
737 if (str_value == null)
738 return false;
740 string assembly_name = AssemblyNameFromXmlns (xmlns);
741 string clr_namespace = ClrNamespaceFromXmlns (xmlns);
742 string type_name = NativeMethods.xaml_get_element_name (data->parser, target_data);
743 string full_name = String.IsNullOrEmpty (clr_namespace) ? type_name : clr_namespace + "." + type_name;
745 Type type = LookupType (data->top_level, assembly_name, full_name);
747 if (type == null || type.IsSubclassOf (typeof (DependencyObject)))
748 return false;
750 // For now just trim the string right here, in the future this should probably be done in the xaml parser
751 object e = ConvertType (null, type, str_value.Trim ());
753 NativeMethods.value_free_value2 ((IntPtr)target_ptr);
755 unsafe {
756 Value *val = (Value *) target_ptr;
758 GCHandle handle = GCHandle.Alloc (e);
759 val->k = Kind.MANAGED;
760 val->u.p = GCHandle.ToIntPtr (handle);
763 return true;
766 private unsafe bool SetProperty (XamlCallbackData *data, string xmlns, Value* target_ptr, IntPtr target_data, Value* target_parent_ptr, string prop_xmlns, string name, Value* value_ptr, IntPtr value_data)
768 string error;
769 object target = Value.ToObject (null, target_ptr);
771 if (target == null) {
772 Console.Error.WriteLine ("target is null: {0} {1} {2}", (IntPtr)target_ptr, name, xmlns);
773 return false;
776 if (name == null) {
777 if (TrySetEnumContentProperty (data, xmlns, target, target_ptr, target_data, value_ptr, value_data))
778 return true;
779 if (TrySetCollectionContentProperty (xmlns, target, target_ptr, target_data, value_ptr, value_data))
780 return true;
781 if (TrySetObjectTextProperty (data, xmlns, target, target_ptr, target_data, value_ptr, value_data))
782 return true;
783 Console.Error.WriteLine ("no property name supplied");
784 return false;
787 string full_name = name;
788 int dot = name.IndexOf ('.');
789 string type_name = null;
791 if (dot >= 0) {
792 type_name = name.Substring (0, dot);
793 if (xmlns != null) {
794 string ns = ClrNamespaceFromXmlns (xmlns);
795 if (ns != null)
796 type_name = String.Concat (ns, ".", type_name);
798 name = name.Substring (++dot, name.Length - dot);
801 if (TrySetExpression (data, xmlns, target, target_data, target_parent_ptr, type_name, prop_xmlns, name, full_name, value_ptr, value_data))
802 return true;
804 if (!IsAttachedProperty (data, target, xmlns, prop_xmlns, full_name)) {
805 if (TrySetPropertyReflection (data, xmlns, target, target_data, target_parent_ptr, type_name, name, value_ptr, value_data, out error))
806 return true;
808 if (TrySetEventReflection (data, xmlns, target, type_name, name, value_ptr, out error))
809 return true;
810 } else {
811 if (TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, value_ptr))
812 return true;
816 return false;
819 private unsafe bool AddChild (XamlCallbackData *data, Value* parent_parent_ptr, bool parent_is_property, string parent_xmlns, Value *parent_ptr, IntPtr parent_data, Value* child_ptr, IntPtr child_data)
821 object parent_parent = Value.ToObject (null, parent_parent_ptr);
822 object parent = Value.ToObject (null, parent_ptr);
823 object child = Value.ToObject (null, child_ptr);
825 if (parent_is_property)
826 return AddChildToProperty (data, parent_parent, parent_xmlns, parent, child, child_data);
828 return AddChildToItem (data, parent_parent_ptr, parent, parent_data, child_ptr, child, child_data);
831 private unsafe bool AddChildToProperty (XamlCallbackData *data, object parent_parent, string parent_xmlns, object parent, object child, IntPtr child_data)
833 string full_prop_name = parent as string;
835 if (full_prop_name == null) {
836 Console.Error.WriteLine ("Attempting to add child to non string parent {0} as a property.", parent);
837 return false;
841 int dot = full_prop_name.IndexOf ('.');
842 if (dot < 1)
843 return false;
844 string type_name = full_prop_name.Substring (0, dot);
845 string prop_name = full_prop_name.Substring (++dot, full_prop_name.Length - dot);
847 Type target_type = TypeFromString (data, parent_xmlns, type_name);
849 if (target_type == null) {
850 Console.Error.WriteLine ("Type '{0}' with xmlns '{1}' could not be found", type_name, parent_xmlns);
851 return false;
854 if (!target_type.IsAssignableFrom (parent_parent.GetType ())) {
855 // This would happen with an attached property, we don't need to do anything here....do we?
856 return false;
859 PropertyInfo pi = parent_parent.GetType ().GetProperty (prop_name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
861 if (pi == null) {
862 Console.Error.WriteLine ("Property does not exist. {0}", prop_name);
863 return false;
866 if (typeof (ResourceDictionary).IsAssignableFrom (pi.PropertyType) && !(child is ResourceDictionary)) {
867 ResourceDictionary the_dict = (ResourceDictionary) pi.GetValue (parent_parent, null);
868 string key_name = NativeMethods.xaml_get_element_key (data->parser, child_data);
870 if (key_name == null) {
871 throw new XamlParseException (2034, "Elements in a ResourceDictionary must have x:Key or x:Name attribute.");
874 if (the_dict == null) {
875 the_dict = (ResourceDictionary) Activator.CreateInstance (pi.PropertyType);
876 if (the_dict == null) {
877 Console.Error.WriteLine ("Unable to create instance of dictionary: " + pi.PropertyType);
878 return false;
880 pi.SetValue (parent_parent, the_dict, null);
883 try {
884 the_dict.Add (key_name, child);
885 if (child is DependencyObject && parent_parent is DependencyObject && !(the_dict is DependencyObject)) {
886 NativeMethods.dependency_object_set_parent_safe (((DependencyObject) child).native, ((DependencyObject) parent_parent).native);
889 return true;
890 } catch (ArgumentException) {
891 throw new XamlParseException (2273, "Elements in the same ResourceDictionary cannot have the same x:Key");
895 if (typeof (IList).IsAssignableFrom (pi.PropertyType) && !(child is IList)) {
896 IList the_list = (IList) pi.GetValue (parent_parent, null);
898 if (the_list == null) {
899 the_list = (IList) Activator.CreateInstance (pi.PropertyType);
900 if (the_list == null) {
901 Console.Error.WriteLine ("Unable to create instance of list: " + pi.PropertyType);
902 return false;
904 pi.SetValue (parent_parent, the_list, null);
907 try {
908 the_list.Add (child);
910 if (child is DependencyObject && parent_parent is DependencyObject && !(the_list is DependencyObject)) {
911 NativeMethods.dependency_object_set_parent_safe (((DependencyObject)child).native, ((DependencyObject)parent_parent).native);
914 return true;
916 catch (Exception e) {
917 Console.WriteLine (e);
918 return false;
922 return true;
925 private unsafe bool AddChildToItem (XamlCallbackData *data, Value *parent_parent_ptr, object parent, IntPtr parent_data, Value *child_ptr, object child, IntPtr child_data)
927 ResourceDictionary the_dict = parent as ResourceDictionary;
928 if (the_dict != null) {
929 string key_name = NativeMethods.xaml_get_element_key (data->parser, child_data);
931 if (key_name == null) {
932 Console.Error.WriteLine ("Attempting to add item to a resource dictionary without an x:Key or x:Name");
933 throw new XamlParseException (-1, -1, "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
936 try {
937 the_dict.Add (key_name, child);
938 if (child is DependencyObject && parent is DependencyObject && !(the_dict is DependencyObject)) {
939 NativeMethods.dependency_object_set_parent_safe (((DependencyObject) child).native, ((DependencyObject) parent).native);
942 return true;
943 } catch (Exception e) {
944 // Fall through to string
945 Console.Error.WriteLine (e);
946 return false;
950 IList the_list = parent as IList;
951 if (the_list != null) {
953 try {
954 the_list.Add (child);
956 if (child is DependencyObject && parent is DependencyObject && !(the_list is DependencyObject)) {
957 NativeMethods.dependency_object_set_parent_safe (((DependencyObject)child).native, ((DependencyObject)parent).native);
960 return true;
962 catch {
963 return false;
967 Type parent_type = parent.GetType ();
968 PropertyInfo pi = GetContentProperty (parent_type);
970 if (pi == null) {
971 Console.Error.WriteLine ("Unable to find content property on type {0}", parent_type);
972 return false;
976 // Is the content property a collection
978 if (typeof (IList).IsAssignableFrom (pi.PropertyType) && !(child is IList)) {
979 the_list = (IList) pi.GetValue (parent, null);
981 if (the_list == null) {
982 the_list = (IList) Activator.CreateInstance (pi.PropertyType);
983 if (the_list == null) {
984 Console.Error.WriteLine ("Unable to create instance of list: " + pi.PropertyType);
985 return false;
987 pi.SetValue (parent, the_list, null);
990 try {
991 the_list.Add (child);
993 if (child is DependencyObject && parent is DependencyObject && !(the_list is DependencyObject)) {
994 NativeMethods.dependency_object_set_parent_safe (((DependencyObject)child).native, ((DependencyObject)parent).native);
996 return true;
998 catch {
999 return false;
1003 string error;
1005 try {
1006 return SetPropertyFromValue (data, parent, parent_data, parent_parent_ptr, pi, child_ptr, child_data, out error);
1007 } catch {
1008 throw new XamlParseException (2010, String.Format ("{0} does not support {1} as content.", parent, child));
1012 private unsafe Type LookupType (Value* top_level, string assembly_name, string full_name)
1014 Type res = null;
1016 if (assembly_name != null) {
1018 // if we're given an explicit assembly
1019 // name, try and load it, then get the
1020 // type from just that assembly
1022 Assembly assembly = null;
1023 if (LoadAssembly (assembly_name, out assembly) == AssemblyLoadResult.Success) {
1024 res = assembly.GetType (full_name);
1025 if (res != null)
1026 return res;
1028 else {
1029 Console.Error.WriteLine ("unable to load assembly for target type.");
1032 else {
1034 // if we're not given an explicit
1035 // assembly name, loop over all
1036 // assemblies specified in
1037 // Deployment.Parts looking for the
1038 // type.
1039 foreach (Assembly a in Deployment.Current.Assemblies) {
1040 res = a.GetType (full_name);
1041 if (res != null)
1042 return res;
1045 Assembly assembly = typeof (DependencyObject).Assembly;
1046 res = assembly.GetType (full_name);
1047 if (res != null && res.IsPublic)
1048 return res;
1052 return Application.GetComponentTypeFromName (full_name);
1055 private unsafe void SetCLRPropertyFromString (XamlCallbackData *data, IntPtr target_data, object target, PropertyInfo pi, string value, out string error, out IntPtr unmanaged_value)
1057 unmanaged_value = IntPtr.Zero;
1058 error = null;
1060 object new_value = null;
1061 bool do_set = true;
1063 try {
1064 if (IsExplicitNull (value)) {
1065 Type t = pi.PropertyType;
1066 if (t.IsValueType && !(t.IsGenericType && t.GetGenericTypeDefinition () == typeof (Nullable<>))) {
1067 error = "Unable to set non nullable type to null.";
1068 return;
1070 new_value = null;
1071 } else
1072 new_value = MoonlightTypeConverter.ConvertObject (pi, value, target.GetType ());
1073 } catch {
1074 do_set = false;
1077 if (do_set) {
1078 try {
1079 SetValue (data, target_data, pi, target, new_value);
1080 return;
1081 } catch (Exception ex) {
1082 error = ex.Message;
1083 return;
1088 // lastly, attempt to create an unmanaged Value* object, if one is created, the managed
1089 // parser will create a managed wrapper for the object and call SetPropertyFromValue with
1090 // the managed object
1092 bool result = NativeMethods.value_from_str_with_typename (TypeToMoonType (pi.PropertyType), pi.Name, value, out unmanaged_value);
1093 if (!result) {
1094 error = string.Format ("unable to convert to type {0} from a string", pi.PropertyType);
1098 private string TypeToMoonType (Type t)
1100 if (t == typeof (double))
1101 return "double";
1102 if (t == typeof (bool))
1103 return "bool";
1104 return t.Name;
1108 // TODO: Is it legal to jam the whole metadata right in the string ie: TargetType="clr-namespace:Mono;MyType"
1110 private unsafe Type TypeFromString (XamlCallbackData *data, string str)
1112 string assembly_name = null;
1113 string full_name = str;
1115 int ps = str.IndexOf (':');
1116 if (ps > 0) {
1117 string xmlns = NativeMethods.xaml_uri_for_prefix (data->parser, str.Substring (0, ps));
1118 string name = str.Substring (ps + 1, str.Length - ps -1);
1120 return TypeFromString (data, xmlns, name);
1123 return LookupType (data->top_level, assembly_name, full_name);
1126 private unsafe Type TypeFromString (XamlCallbackData *data, string xmlns, string name)
1128 string clr_namespace = ClrNamespaceFromXmlns (xmlns);
1129 string assembly_name = AssemblyNameFromXmlns (xmlns);
1131 string full_name = string.IsNullOrEmpty (clr_namespace) ? name : clr_namespace + "." + name;
1133 return LookupType (data->top_level, assembly_name, full_name);
1136 private unsafe DependencyProperty DependencyPropertyFromString (XamlCallbackData *data, object otarget, Value* target_parent_ptr, string str_value)
1138 object o = Value.ToObject (null, target_parent_ptr);
1139 Style parent = o as Style;
1141 if (parent == null) {
1142 Console.Error.WriteLine ("DependencyPropertyFromString Parent of target is not a Style. It's a {0}", o);
1143 return null;
1146 Type target_type = parent.TargetType;
1147 if (target_type == null) {
1148 Console.Error.WriteLine ("DependencyPropertyFromString TargetType is null.");
1149 return null;
1153 // Check to see if we have an attached property
1155 int dot = str_value.IndexOf ('.');
1156 if (dot >= 0) {
1157 string type_name = str_value.Substring (0, dot);
1158 str_value= str_value.Substring (++dot, str_value.Length - dot);
1160 target_type = TypeFromString (data, type_name);
1163 Types.Ensure (target_type);
1165 ManagedType mt = Deployment.Current.Types.Find (target_type);
1166 DependencyProperty dp = DependencyProperty.Lookup ((Kind) mt.native_handle, str_value);
1168 return dp;
1171 private unsafe bool SetPropertyFromValue (XamlCallbackData *data, object target, IntPtr target_data, Value* target_parent_ptr, PropertyInfo pi, Value* value_ptr, IntPtr value_data, out string error)
1173 error = null;
1174 object obj_value = Value.ToObject (null, value_ptr);
1176 if (pi.GetCustomAttributes (typeof (SetPropertyDelayedAttribute), true).Length > 0) {
1177 if ((data->flags & XamlCallbackFlags.SettingDelayedProperty) == 0) {
1178 Value v = *value_ptr;
1179 NativeMethods.xaml_delay_set_property (data->parser, target_data, null, pi.Name, ref v);
1180 return true;
1184 if (obj_value is Binding && target is FrameworkElement) {
1185 FrameworkElement fe = (FrameworkElement) target;
1186 fe.SetBinding (DependencyProperty.Lookup (fe.GetKind (), pi.Name), (Binding) obj_value);
1187 return true;
1190 if (obj_value is StaticResource) {
1191 StaticResource sr = (StaticResource)obj_value;
1192 obj_value = "{StaticResource " + sr.ResourceKey + "}";
1195 if (typeof (IList).IsAssignableFrom (pi.PropertyType) && !(obj_value is IList)) {
1196 // This case is handled in the AddChild code
1197 return true;
1200 if (typeof (ResourceDictionary).IsAssignableFrom (pi.PropertyType) && !(obj_value is ResourceDictionary)) {
1201 // This case is handled in the AddChild code
1202 return true;
1205 string str_value = obj_value as string;
1206 if (str_value != null) {
1207 IntPtr unmanaged_value;
1209 if (pi.PropertyType == typeof (Type)) {
1210 Type t = TypeFromString (data, str_value);
1211 if (t != null) {
1212 SetValue (data, target_data, pi, target, t);
1213 return true;
1217 if (pi.PropertyType == typeof (DependencyProperty)) {
1218 DependencyProperty dp = DependencyPropertyFromString (data, target, target_parent_ptr, str_value);
1219 if (dp != null) {
1220 SetValue (data, target_data, pi, target, dp);
1221 return true;
1225 if (typeof (System.Windows.Data.Binding).IsAssignableFrom (pi.PropertyType) && MarkupExpressionParser.IsBinding (str_value)) {
1226 MarkupExpressionParser p = new MarkupExpressionParser (null, pi.Name, data->parser, target_data);
1228 string expression = str_value;
1229 obj_value = p.ParseExpression (ref expression);
1231 if (!(obj_value is Binding))
1232 return false;
1234 SetValue (data, target_data, pi, target, obj_value);
1235 return true;
1238 if (MarkupExpressionParser.IsStaticResource (str_value)) {
1239 // FIXME: The NUnit tests show we need to use the parent of the target to resolve
1240 // the StaticResource, but are there any cases where we should use the actual target?
1241 DependencyObject parent = Value.ToObject (null, target_parent_ptr) as DependencyObject;
1242 if (parent == null)
1243 return false;
1244 MarkupExpressionParser p = new MarkupExpressionParser (parent, "", data->parser, target_data);
1245 obj_value = p.ParseExpression (ref str_value);
1246 obj_value = ConvertType (pi, pi.PropertyType, obj_value);
1248 SetValue (data, target_data, pi, target, obj_value);
1249 return true;
1252 SetCLRPropertyFromString (data, target_data, target, pi, str_value, out error, out unmanaged_value);
1254 if (error == null && unmanaged_value != IntPtr.Zero)
1255 obj_value = Value.ToObject (null, unmanaged_value);
1256 else
1257 return error == null;
1258 } else {
1259 obj_value = Value.ToObject (pi.PropertyType, value_ptr);
1262 obj_value = ConvertType (pi, pi.PropertyType, obj_value);
1263 SetValue (data, target_data, pi, target, obj_value);
1265 return true;
1268 private static unsafe void SetValue (XamlCallbackData *data, IntPtr target_data, PropertyInfo pi, object target, object value)
1270 SetterBase sb = target as SetterBase;
1272 if (sb != null)
1273 sb.IsSealed = false;
1275 try {
1276 if (NativeMethods.xaml_is_property_set (data->parser, target_data, pi.Name))
1277 throw new XamlParseException (2033, String.Format ("Cannot specify the value multiple times for property: {0}.", pi.Name));
1279 pi.SetValue (target, value, null);
1281 NativeMethods.xaml_mark_property_as_set (data->parser, target_data, pi.Name);
1283 } finally {
1284 if (sb != null)
1285 sb.IsSealed = true;
1289 private static object ConvertType (MemberInfo pi, Type t, object value)
1291 if (value == null)
1292 return null;
1294 Type valueType = value.GetType ();
1295 if (valueType == t)
1296 return value;
1298 try {
1299 if (t.IsEnum) {
1300 string str_value = value as string;
1301 if (str_value != null)
1302 return Enum.Parse (t, str_value, true);
1303 if (Enum.IsDefined (t, value))
1304 return Enum.ToObject (t, value);
1306 } catch {
1309 TypeConverter converter = Helper.GetConverterFor (pi, t);
1310 if (converter == null) {
1311 try {
1312 converter = new MoonlightTypeConverter (pi == null ? null : pi.Name, t);
1313 } catch {
1314 converter = null;
1318 if (converter != null && converter.CanConvertFrom (value.GetType ()))
1319 return converter.ConvertFrom (value);
1321 try {
1322 if (!valueType.IsSubclassOf (t))
1323 value = Convert.ChangeType (value, t, System.Globalization.CultureInfo.CurrentCulture);
1324 } catch {
1327 // This will just let things fail
1328 return value;
1331 private static string ClrNamespaceFromXmlns (string xmlns)
1333 if (String.IsNullOrEmpty (xmlns))
1334 return null;
1336 int start = xmlns.IndexOf ("clr-namespace:");
1338 if (start < 0)
1339 return null;
1340 start += "clr-namespace:".Length;
1342 int end = xmlns.IndexOf (';', start);
1343 if (end == -1)
1344 end = xmlns.Length;
1346 return xmlns.Substring (start, end - start);
1349 private static string AssemblyNameFromXmlns (string xmlns)
1351 if (String.IsNullOrEmpty (xmlns))
1352 return null;
1354 int start = xmlns.IndexOf ("assembly=");
1355 if (start < 0)
1356 return null;
1358 start += "assembly=".Length;
1359 int end = xmlns.IndexOf (';', start);
1360 if (end == -1)
1361 end = xmlns.Length;
1362 return xmlns.Substring (start, end - start);
1365 private static bool ValidateXmlns (string xmlns)
1367 Uri dummy = null;
1368 if (Uri.TryCreate (xmlns, UriKind.Absolute, out dummy))
1369 return true;
1371 int start = xmlns.IndexOf ("clr-namespace");
1372 int end = start + "clr-namespace".Length;
1373 if (end >= xmlns.Length || xmlns [end] != ':')
1374 return false;
1376 start = xmlns.IndexOf ("assembly");
1377 if (start > 0) {
1378 end = start + "assembly".Length;
1379 if (end >= xmlns.Length || xmlns [end] != '=')
1380 return false;
1383 return true;
1386 private unsafe MethodInfo GetSetMethodForAttachedProperty (Value *top_level, string xmlns, string type_name, string full_type_name, string prop_name)
1388 string assembly_name = AssemblyNameFromXmlns (xmlns);
1389 string ns = ClrNamespaceFromXmlns (xmlns);
1391 if (assembly_name == null && !TryGetDefaultAssemblyName (top_level, out assembly_name)) {
1392 Console.Error.WriteLine ("Unable to find an assembly to load type from.");
1393 return null;
1396 Assembly clientlib;
1397 if (LoadAssembly (assembly_name, out clientlib) != AssemblyLoadResult.Success) {
1398 Console.Error.WriteLine ("couldn't load assembly: {0} namespace: {1}", assembly_name, ns);
1399 return null;
1402 Type attach_type = clientlib.GetType (full_type_name, false);
1403 if (attach_type == null) {
1404 attach_type = Application.GetComponentTypeFromName (type_name);
1405 if (attach_type == null) {
1406 Console.Error.WriteLine ("attach type is null type name: {0} full type name: {1}", type_name, full_type_name);
1407 return null;
1411 MethodInfo set_method = attach_type.GetMethod (String.Concat ("Set", prop_name), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
1412 return set_method;
1415 private static unsafe object GetObjectValue (object target, IntPtr target_data, string prop_name, IntPtr parser, Value* value_ptr, out string error)
1417 error = null;
1419 IntPtr unmanaged_value = IntPtr.Zero;
1420 object o_value = Value.ToObject (null, value_ptr);
1421 if (error == null && unmanaged_value != IntPtr.Zero)
1422 o_value = Value.ToObject (null, unmanaged_value);
1424 if (o_value is String && MarkupExpressionParser.IsStaticResource ((string) o_value)) {
1425 MarkupExpressionParser mp = new MarkupExpressionParser ((DependencyObject) target, prop_name, parser, target_data);
1426 string str_value = o_value as String;
1427 o_value = mp.ParseExpression (ref str_value);
1430 return o_value;
1433 private static bool IsExplicitNull (string value)
1435 return Regex.IsMatch (value, "^{\\s*x:Null\\s*}");
1438 private PropertyInfo GetContentProperty (Type t)
1440 Type walk = t;
1441 string content_property = null;
1443 while (walk != null) {
1444 content_property = GetContentPropertyNameForType (walk);
1445 if (content_property != null)
1446 break;
1447 walk = walk.BaseType;
1450 if (walk == null || content_property == null)
1451 return null;
1453 PropertyInfo pi = walk.GetProperty (content_property, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
1454 return pi;
1457 private string GetContentPropertyNameForType (Type t)
1459 object [] o = t.GetCustomAttributes (typeof (ContentPropertyAttribute), false);
1461 if (o.Length == 0)
1462 return null;
1464 ContentPropertyAttribute cpa = (ContentPropertyAttribute ) o [0];
1465 return cpa.Name;
1468 private string GetContentPropertyName (Type t)
1470 object [] o = t.GetCustomAttributes (typeof (ContentPropertyAttribute), true);
1471 if (o.Length == 0)
1472 return null;
1473 ContentPropertyAttribute cpa = (ContentPropertyAttribute ) o [0];
1475 return cpa.Name;
1480 /// Callbacks invoked by the xaml.cpp C++ parser
1484 #region Callbacks from xaml.cpp
1486 // Proxy so that we return IntPtr.Zero in case of any failures, instead of
1487 // genereting an exception and unwinding the stack.
1489 private unsafe bool cb_lookup_object (XamlCallbackData *data, Value* parent, string xmlns, string name, bool create, bool is_property, out Value value, ref MoonError error)
1491 try {
1492 return LookupObject (data->top_level, parent, xmlns, name, create, is_property, out value);
1493 } catch (Exception ex) {
1494 Console.Error.WriteLine ("ManagedXamlLoader::LookupObject ({0}, {1}, {2}, {3}) failed: {3} ({4}).", (IntPtr) data->top_level, xmlns, create, name, ex.Message, ex.GetType ().FullName);
1495 Console.WriteLine (ex);
1496 value = Value.Empty;
1497 error = new MoonError (ex);
1498 return false;
1502 private void cb_create_gchandle ()
1504 if (!handle.IsAllocated)
1505 handle = GCHandle.Alloc (this);
1509 // Proxy so that we return IntPtr.Zero in case of any failures, instead of
1510 // generating an exception and unwinding the stack.
1512 private unsafe bool cb_set_property (XamlCallbackData *data, string xmlns, Value* target, IntPtr target_data, Value* target_parent, string prop_xmlns, string name, Value* value_ptr, IntPtr value_data, ref MoonError error)
1514 try {
1515 return SetProperty (data, xmlns, target, target_data, target_parent, prop_xmlns, name, value_ptr, value_data);
1516 } catch (Exception ex) {
1517 try {
1518 Console.Error.WriteLine ("ManagedXamlLoader::SetProperty ({0}, {1}, {2}, {3}, {4}) threw an exception: {5}.", (IntPtr) data->top_level, xmlns, (IntPtr)target, name, (IntPtr)value_ptr, ex.Message);
1519 Console.Error.WriteLine (ex);
1520 error = new MoonError (ex);
1521 return false;
1523 catch {
1524 return false;
1529 private unsafe bool cb_import_xaml_xmlns (XamlCallbackData *data, string xmlns, ref MoonError error)
1531 try {
1532 if (!ValidateXmlns (xmlns))
1533 return false;
1534 Application.ImportXamlNamespace (xmlns);
1535 return true;
1536 } catch (Exception ex) {
1537 Console.WriteLine ("Application::ImportXamlNamespace ({0}) threw an exception:\n{1}", xmlns, ex);
1538 error = new MoonError (ex);
1539 return false;
1544 private unsafe string cb_get_content_property_name (XamlCallbackData *data, Value* object_ptr, ref MoonError error)
1546 object obj = Value.ToObject (null, object_ptr);
1548 if (obj == null)
1549 return null;
1551 Type t = obj.GetType ();
1552 return GetContentPropertyName (t);
1556 private unsafe bool cb_add_child (XamlCallbackData *data, Value* parent_parent, bool parent_is_property, string parent_xmlns, Value *parent, IntPtr parent_data, Value* child, IntPtr child_data, ref MoonError error)
1558 try {
1559 return AddChild (data, parent_parent, parent_is_property, parent_xmlns, parent, parent_data, child, child_data);
1560 } catch (Exception ex) {
1561 Console.Error.WriteLine (ex);
1562 error = new MoonError (ex);
1563 return false;
1568 #endregion