ConventionRegistry.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. namespace MongoDB.Bson.Serialization.Conventions
  18. {
  19. /// <summary>
  20. /// Represents a registry of conventions.
  21. /// </summary>
  22. public static class ConventionRegistry
  23. {
  24. // private static fields
  25. private readonly static List<ConventionPackContainer> __conventionPacks = new List<ConventionPackContainer>();
  26. private readonly static object __lock = new object();
  27. // static constructors
  28. static ConventionRegistry()
  29. {
  30. Register("__defaults__", DefaultConventionPack.Instance, t => true);
  31. Register("__attributes__", AttributeConventionPack.Instance, t => true);
  32. }
  33. // public static methods
  34. /// <summary>
  35. /// Looks up the effective set of conventions that apply to a type.
  36. /// </summary>
  37. /// <param name="type">The type.</param>
  38. /// <returns>The conventions for that type.</returns>
  39. public static IConventionPack Lookup(Type type)
  40. {
  41. if (type == null)
  42. {
  43. throw new ArgumentNullException("type");
  44. }
  45. lock (__lock)
  46. {
  47. var pack = new ConventionPack();
  48. // append any attribute packs (usually just one) at the end so attributes are processed last
  49. var attributePacks = new List<IConventionPack>();
  50. foreach (var container in __conventionPacks)
  51. {
  52. if (container.Filter(type))
  53. {
  54. if (container.Name == "__attributes__")
  55. {
  56. attributePacks.Add(container.Pack);
  57. }
  58. else
  59. {
  60. pack.Append(container.Pack);
  61. }
  62. }
  63. }
  64. foreach (var attributePack in attributePacks)
  65. {
  66. pack.Append(attributePack);
  67. }
  68. return pack;
  69. }
  70. }
  71. /// <summary>
  72. /// Registers the conventions.
  73. /// </summary>
  74. /// <param name="name">The name.</param>
  75. /// <param name="conventions">The conventions.</param>
  76. /// <param name="filter">The filter.</param>
  77. public static void Register(string name, IConventionPack conventions, Func<Type, bool> filter)
  78. {
  79. if (name == null)
  80. {
  81. throw new ArgumentNullException("name");
  82. }
  83. if (conventions == null)
  84. {
  85. throw new ArgumentNullException("conventions");
  86. }
  87. if (filter == null)
  88. {
  89. throw new ArgumentNullException("filter");
  90. }
  91. lock (__lock)
  92. {
  93. var container = new ConventionPackContainer
  94. {
  95. Filter = filter,
  96. Name = name,
  97. Pack = conventions
  98. };
  99. __conventionPacks.Add(container);
  100. }
  101. }
  102. /// <summary>
  103. /// Removes the conventions specified by the given name.
  104. /// </summary>
  105. /// <param name="name">The name.</param>
  106. /// <remarks>Removing a convention allows the removal of the special __defaults__ conventions
  107. /// and the __attributes__ conventions for those who want to completely customize the
  108. /// experience.</remarks>
  109. public static void Remove(string name)
  110. {
  111. if (name == null)
  112. {
  113. throw new ArgumentNullException("name");
  114. }
  115. lock (__lock)
  116. {
  117. __conventionPacks.RemoveAll(x => x.Name == name);
  118. }
  119. }
  120. // private class
  121. private class ConventionPackContainer
  122. {
  123. public Func<Type, bool> Filter;
  124. public string Name;
  125. public IConventionPack Pack;
  126. }
  127. }
  128. }