PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/Amf/AmfClassDescriptor.cs

https://bitbucket.org/VahidN/interlace
C# | 164 lines | 104 code | 31 blank | 29 comment | 14 complexity | aa6427e59367d9ce2a021bb86cd392b2 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Reflection;
  30. using System.Text;
  31. #endregion
  32. namespace Interlace.Amf
  33. {
  34. public class AmfClassDescriptor : IAmfClassDescriptor
  35. {
  36. Type _type;
  37. AmfClassAttribute _classAttribute;
  38. List<AmfPropertyDescriptor> _properties;
  39. AmfTraits _serializationTraits = null;
  40. public AmfClassDescriptor(Type type)
  41. {
  42. _type = type;
  43. object[] classAttributes = type.GetCustomAttributes(typeof(AmfClassAttribute), true);
  44. if (classAttributes.Length != 1) throw new ArgumentException("The specified type is not marked with the AmfClassAttribute.", "type");
  45. _classAttribute = classAttributes[0] as AmfClassAttribute;
  46. _properties = new List<AmfPropertyDescriptor>();
  47. foreach (PropertyInfo property in type.GetProperties())
  48. {
  49. object[] propertyAttributes = property.GetCustomAttributes(typeof(AmfPropertyAttribute), true);
  50. if (propertyAttributes.Length == 0) continue;
  51. AmfPropertyDescriptor descriptor = new AmfPropertyDescriptor(property, propertyAttributes[0] as AmfPropertyAttribute);
  52. _properties.Add(descriptor);
  53. }
  54. }
  55. public string Alias
  56. {
  57. get { return _classAttribute.Alias; }
  58. }
  59. public object BeginDeserialization(AmfTraits traits)
  60. {
  61. return Activator.CreateInstance(_type);
  62. }
  63. public void EndDeserialization(AmfTraits traits, object deserializingTo, IDictionary<string, object> staticMembers, IDictionary<string, object> dynamicMembers)
  64. {
  65. // Set the dynamic properties:
  66. if (traits.Kind == AmfTraitsKind.Dynamic)
  67. {
  68. if (!(deserializingTo is AmfObject)) throw new AmfException(string.Format(
  69. "The AMF decoder received a dynamic object but the registered class for the object (\"{0}\") " +
  70. "does not support dynamic properties (it does not inherit from AmfObject).", Alias));
  71. AmfObject amfObj = deserializingTo as AmfObject;
  72. foreach (KeyValuePair<string, object> pair in dynamicMembers)
  73. {
  74. amfObj.Properties[pair.Key] = pair.Value;
  75. }
  76. }
  77. // Check for unexpected properties:
  78. if (_properties.Count != staticMembers.Count)
  79. {
  80. // (If the property count is equal and there is an unexpected property, there
  81. // must also be a missing property that will trigger later).
  82. Dictionary<string, bool> receivedProperties = new Dictionary<string, bool>();
  83. foreach (string key in staticMembers.Keys)
  84. {
  85. receivedProperties[key] = true;
  86. }
  87. foreach (AmfPropertyDescriptor descriptor in _properties)
  88. {
  89. foreach (string propertyName in descriptor.GetUsedPropertyNames(this))
  90. {
  91. if (!receivedProperties.ContainsKey(propertyName))
  92. {
  93. throw new AmfException(string.Format(
  94. "The class registered for the alias \"{0}\" was received but was has an unexpected " +
  95. "property (\"{1}\").", Alias, propertyName));
  96. }
  97. }
  98. }
  99. }
  100. foreach (AmfPropertyDescriptor descriptor in _properties)
  101. {
  102. descriptor.DeserializeProperty(this, deserializingTo, staticMembers);
  103. }
  104. }
  105. public void SerializeObject(object value, out AmfTraits traits, out IDictionary<string, object> staticMembers, out IDictionary<string, object> dynamicMembers)
  106. {
  107. if (_serializationTraits == null)
  108. {
  109. List<string> memberNames = new List<string>();
  110. foreach (AmfPropertyDescriptor property in _properties)
  111. {
  112. memberNames.AddRange(property.GetUsedPropertyNames(this));
  113. }
  114. _serializationTraits = new AmfTraits(_classAttribute.Alias,
  115. _type.IsSubclassOf(typeof(AmfObject)) ? AmfTraitsKind.Dynamic : AmfTraitsKind.Static, memberNames.ToArray());
  116. }
  117. traits = _serializationTraits;
  118. if (_serializationTraits.Kind == AmfTraitsKind.Dynamic)
  119. {
  120. dynamicMembers = (value as AmfObject).Properties;
  121. }
  122. else
  123. {
  124. dynamicMembers = null;
  125. }
  126. staticMembers = new Dictionary<string, object>();
  127. foreach (AmfPropertyDescriptor property in _properties)
  128. {
  129. property.SerializeProperty(this, value, staticMembers);
  130. }
  131. }
  132. }
  133. }