/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
namespace MongoDB.Bson.Serialization.Conventions
{
///
/// Represents a registry of conventions.
///
public static class ConventionRegistry
{
// private static fields
private readonly static List __conventionPacks = new List();
private readonly static object __lock = new object();
// static constructors
static ConventionRegistry()
{
Register("__defaults__", DefaultConventionPack.Instance, t => true);
Register("__attributes__", AttributeConventionPack.Instance, t => true);
}
// public static methods
///
/// Looks up the effective set of conventions that apply to a type.
///
/// The type.
/// The conventions for that type.
public static IConventionPack Lookup(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
lock (__lock)
{
var pack = new ConventionPack();
// append any attribute packs (usually just one) at the end so attributes are processed last
var attributePacks = new List();
foreach (var container in __conventionPacks)
{
if (container.Filter(type))
{
if (container.Name == "__attributes__")
{
attributePacks.Add(container.Pack);
}
else
{
pack.Append(container.Pack);
}
}
}
foreach (var attributePack in attributePacks)
{
pack.Append(attributePack);
}
return pack;
}
}
///
/// Registers the conventions.
///
/// The name.
/// The conventions.
/// The filter.
public static void Register(string name, IConventionPack conventions, Func filter)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
if (conventions == null)
{
throw new ArgumentNullException("conventions");
}
if (filter == null)
{
throw new ArgumentNullException("filter");
}
lock (__lock)
{
var container = new ConventionPackContainer
{
Filter = filter,
Name = name,
Pack = conventions
};
__conventionPacks.Add(container);
}
}
///
/// Removes the conventions specified by the given name.
///
/// The name.
/// Removing a convention allows the removal of the special __defaults__ conventions
/// and the __attributes__ conventions for those who want to completely customize the
/// experience.
public static void Remove(string name)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
lock (__lock)
{
__conventionPacks.RemoveAll(x => x.Name == name);
}
}
// private class
private class ConventionPackContainer
{
public Func Filter;
public string Name;
public IConventionPack Pack;
}
}
}