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

/src/sys/dotnet/fan/sys/Field.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 179 lines | 120 code | 30 blank | 29 comment | 33 complexity | babc253bd6c085036d5810e6b4069164 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2006, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 27 Sep 06 Andy Frank Creation
  7. //
  8. using System;
  9. using System.Collections;
  10. using System.Reflection;
  11. using Fanx.Fcode;
  12. using Fanx.Util;
  13. namespace Fan.Sys
  14. {
  15. /// <summary>
  16. /// Field is a slot which "stores" a value.
  17. /// </summary>
  18. public class Field : Slot
  19. {
  20. //////////////////////////////////////////////////////////////////////////
  21. // Factories
  22. //////////////////////////////////////////////////////////////////////////
  23. public static Func makeSetFunc(Map map)
  24. {
  25. return new SetFunc(map);
  26. }
  27. internal class SetFunc : Func.Indirect1
  28. {
  29. internal SetFunc(Map map) { m_map = map; }
  30. public override Object call(Object obj)
  31. {
  32. IDictionaryEnumerator en = m_map.pairsIterator();
  33. while (en.MoveNext())
  34. {
  35. Field field = (Field)en.Key;
  36. object val = en.Value;
  37. field.set(obj, val, obj != m_inCtor);
  38. }
  39. return null;
  40. }
  41. Map m_map;
  42. }
  43. //////////////////////////////////////////////////////////////////////////
  44. // C# Constructors
  45. //////////////////////////////////////////////////////////////////////////
  46. public Field(Type parent, string name, int flags, Facets facets, int lineNum, Type type)
  47. : base(parent, name, flags, facets, lineNum)
  48. {
  49. this.m_type = type;
  50. }
  51. //////////////////////////////////////////////////////////////////////////
  52. // Signature
  53. //////////////////////////////////////////////////////////////////////////
  54. public override Type @typeof() { return Sys.FieldType; }
  55. public Type type() { return m_type; }
  56. public override string signature() { return m_type.toStr() + " " + m_name; }
  57. public override object trap(string name, List args)
  58. {
  59. // private undocumented access
  60. if (name == "getter") return m_getter;
  61. if (name == "setter") return m_setter;
  62. return base.trap(name, args);
  63. }
  64. //////////////////////////////////////////////////////////////////////////
  65. // Reflection
  66. //////////////////////////////////////////////////////////////////////////
  67. public object get() { return get(null); }
  68. public virtual object get(object instance)
  69. {
  70. m_parent.finish();
  71. if (m_getter != null)
  72. {
  73. return m_getter.invoke(instance, Method.noArgs);
  74. }
  75. try
  76. {
  77. return FanUtil.box(m_reflect.GetValue(instance));
  78. }
  79. catch (Exception e)
  80. {
  81. if (m_reflect == null)
  82. throw Err.make("Field not mapped to System.Reflection.FieldInfo correctly").val;
  83. throw Err.make(e).val;
  84. }
  85. }
  86. public virtual void set(object instance, object value)
  87. {
  88. set(instance, value, true);
  89. }
  90. public virtual void set(object instance, object value, bool checkConst)
  91. {
  92. m_parent.finish();
  93. // check const
  94. if ((m_flags & FConst.Const) != 0)
  95. {
  96. if (checkConst)
  97. throw ReadonlyErr.make("Cannot set const field " + qname()).val;
  98. else if (value != null && !isImmutable(value))
  99. throw ReadonlyErr.make("Cannot set const field " + qname() + " with mutable value").val;
  100. }
  101. // check static
  102. if ((m_flags & FConst.Static) != 0)
  103. throw ReadonlyErr.make("Cannot set static field " + qname()).val;
  104. // check generic type (the .NET runtime will check non-generics)
  105. if (m_type.isGenericInstance() && value != null)
  106. {
  107. if (!@typeof(value).@is(m_type.toNonNullable()))
  108. throw ArgErr.make("Wrong type for field " + qname() + ": " + m_type + " != " + @typeof(value)).val;
  109. }
  110. if (m_setter != null)
  111. {
  112. m_setter.invoke(instance, new object[] { value });
  113. return;
  114. }
  115. try
  116. {
  117. m_reflect.SetValue(instance, unbox(value));
  118. }
  119. catch (ArgumentException e)
  120. {
  121. throw ArgErr.make(e).val;
  122. }
  123. catch (Exception e)
  124. {
  125. if (m_reflect == null)
  126. throw Err.make("Field not mapped to System.Reflection correctly").val;
  127. throw Err.make(e).val;
  128. }
  129. }
  130. object unbox(object val)
  131. {
  132. System.Type t = m_reflect.FieldType;
  133. if (val is Boolean) return t == BoolType ? ((Boolean)val).booleanValue() : val;
  134. if (val is Double) return t == DoubleType ? ((Double)val).doubleValue() : val;
  135. if (val is Long) return t == Int64Type ? ((Long)val).longValue() : val;
  136. return val;
  137. }
  138. //////////////////////////////////////////////////////////////////////////
  139. // Fields
  140. //////////////////////////////////////////////////////////////////////////
  141. static System.Type BoolType = System.Type.GetType("System.Boolean");
  142. static System.Type DoubleType = System.Type.GetType("System.Double");
  143. static System.Type Int64Type = System.Type.GetType("System.Int64");
  144. internal Type m_type;
  145. internal Method m_getter;
  146. internal Method m_setter;
  147. internal FieldInfo m_reflect;
  148. }
  149. }