PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ReactiveUI/BindingTypeConverters.cs

https://github.com/bsiegel/ReactiveUI
C# | 141 lines | 114 code | 21 blank | 6 comment | 23 complexity | 41cbe0130bf9e10a64b452c46f3e12a1 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0, LGPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics.Contracts;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text;
  8. namespace ReactiveUI
  9. {
  10. public class EqualityTypeConverter : IBindingTypeConverter
  11. {
  12. public int GetAffinityForObjects(Type lhs, Type rhs)
  13. {
  14. if (rhs.IsAssignableFrom(lhs)) {
  15. return 100;
  16. }
  17. // NB: WPF is terrible.
  18. if (lhs == typeof (object)) {
  19. return 100;
  20. }
  21. var realType = Nullable.GetUnderlyingType(lhs);
  22. if (realType != null) {
  23. return GetAffinityForObjects(realType, rhs);
  24. }
  25. realType = Nullable.GetUnderlyingType(rhs);
  26. if (realType != null) {
  27. return GetAffinityForObjects(lhs, realType);
  28. }
  29. return 0;
  30. }
  31. static MethodInfo genericMi = null;
  32. static MemoizingMRUCache<Type, MethodInfo> referenceCastCache = new MemoizingMRUCache<Type, MethodInfo>((t, _) => {
  33. genericMi = genericMi ??
  34. typeof (EqualityTypeConverter).GetMethod("DoReferenceCast", BindingFlags.Public | BindingFlags.Static);
  35. return genericMi.MakeGenericMethod(new[] {t});
  36. }, 25);
  37. public bool TryConvert(object from, Type toType, object conversionHint, out object result)
  38. {
  39. Contract.Requires(toType != null);
  40. var mi = referenceCastCache.Get(toType);
  41. try {
  42. result = mi.Invoke(null, new[] {from});
  43. } catch (Exception ex) {
  44. this.Log().WarnException("Couldn't convert object to type: " + toType, ex);
  45. result = null;
  46. return false;
  47. }
  48. return true;
  49. }
  50. public static object DoReferenceCast<T>(object from)
  51. {
  52. var targetType = typeof (T);
  53. var backingNullableType = Nullable.GetUnderlyingType(targetType);
  54. if (backingNullableType == null) {
  55. return (T) from;
  56. }
  57. if (from == null) {
  58. var ut = Nullable.GetUnderlyingType(targetType);
  59. if (ut == null) {
  60. throw new Exception("Can't convert from nullable-type which is null to non-nullable type");
  61. }
  62. return default(T);
  63. }
  64. return (T) Convert.ChangeType(from, backingNullableType, null);
  65. }
  66. }
  67. public class StringConverter : IBindingTypeConverter
  68. {
  69. public int GetAffinityForObjects(Type lhs, Type rhs)
  70. {
  71. return (rhs == typeof (string) ? 2 : 0);
  72. }
  73. public bool TryConvert(object from, Type toType, object conversionHint, out object result)
  74. {
  75. // XXX: All Of The Localization
  76. result = from.ToString();
  77. return true;
  78. }
  79. }
  80. #if !SILVERLIGHT && !WINRT
  81. public class ComponentModelTypeConverter : IBindingTypeConverter
  82. {
  83. readonly MemoizingMRUCache<Tuple<Type, Type>, TypeConverter> typeConverterCache = new MemoizingMRUCache<Tuple<Type, Type>, TypeConverter>((types, _) => {
  84. // NB: String is a Magical Type(tm) to TypeConverters. If we are
  85. // converting from string => int, we need the Int converter, not
  86. // the string converter :-/
  87. if (types.Item1 == typeof (string)) {
  88. types = Tuple.Create(types.Item2, types.Item1);
  89. }
  90. var converter = TypeDescriptor.GetConverter(types.Item1);
  91. return converter.CanConvertTo(types.Item2) ? converter : null;
  92. }, 25);
  93. public int GetAffinityForObjects(Type lhs, Type rhs)
  94. {
  95. var converter = typeConverterCache.Get(Tuple.Create(lhs, rhs));
  96. return converter != null ? 10 : 0;
  97. }
  98. public bool TryConvert(object from, Type toType, object conversionHint, out object result)
  99. {
  100. if (from == null) {
  101. result = null;
  102. return true;
  103. }
  104. var fromType = from.GetType();
  105. var converter = typeConverterCache.Get(Tuple.Create(fromType, toType));
  106. if (converter == null) {
  107. throw new ArgumentException(String.Format("Can't convert {0} to {1}. To fix this, register a IBindingTypeConverter", fromType, toType));
  108. }
  109. try {
  110. // TODO: This should use conversionHint to determine whether this is locale-aware or not
  111. result = converter.ConvertTo(from, toType);
  112. return true;
  113. } catch (FormatException) {
  114. result = null;
  115. return false;
  116. }
  117. }
  118. }
  119. #endif
  120. }