// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PropertyDataManager.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// Property data manager.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
namespace Catel.Data
{
/// <summary>
/// Property data manager.
/// </summary>
internal class PropertyDataManager
{
#region Variables
/// <summary>
/// Dictionary containing all the properties per type.
/// </summary>
private readonly Dictionary<Type, Dictionary<string, PropertyData>> _propertyData = new Dictionary<Type, Dictionary<string, PropertyData>>();
/// <summary>
/// Lock object for the <see cref="_propertyData"/> field.
/// </summary>
private readonly object _propertyDataLock = new object();
/// <summary>
/// Dictionary to provide fast xml name to property name mappings.
/// </summary>
private readonly Dictionary<Type, Dictionary<string, string>> _xmlNameToPropertyNameMappings = new Dictionary<Type, Dictionary<string, string>>();
/// <summary>
/// Dictionary to provide fast property name to xml name mappings.
/// </summary>
private readonly Dictionary<Type, Dictionary<string, string>> _xmlPropertyNameToXmlNameMappings = new Dictionary<Type, Dictionary<string, string>>();
#endregion
#region Constructor & destructor
#endregion
#region Properties
#endregion
#region Methods
/// <summary>
/// Gets the properties of a specific type.
/// </summary>
/// <param name="type">The type for which the properties to return.</param>
/// <returns>Dictionary with the properties.</returns>
public Dictionary<string, PropertyData> GetProperties(Type type)
{
return _propertyData.ContainsKey(type) ? _propertyData[type] : new Dictionary<string, PropertyData>();
}
/// <summary>
/// Registers a property for a specific type.
/// </summary>
/// <param name="type">The type for which to register the property.</param>
/// <param name="name">The name of the property.</param>
/// <param name="propertyData">The property data.</param>
public void RegisterProperty(Type type, string name, PropertyData propertyData)
{
lock (_propertyDataLock)
{
if (!_propertyData.ContainsKey(type))
{
_propertyData.Add(type, new Dictionary<string, PropertyData>());
}
if (_propertyData[type].ContainsKey(name))
{
throw new PropertyAlreadyRegisteredException(name, type);
}
_propertyData[type].Add(name, propertyData);
}
}
/// <summary>
/// Returns whether a specific property is registered.
/// </summary>
/// <param name="type">The type for which to check whether the property is registered.</param>
/// <param name="name">The name of the property.</param>
/// <returns>
/// True if the property is registered, otherwise false.
/// </returns>
public bool IsPropertyRegistered(Type type, string name)
{
lock (_propertyDataLock)
{
if (_propertyData.ContainsKey(type))
{
return _propertyData[type].ContainsKey(name);
}
return false;
}
}
/// <summary>
/// Gets the property data.
/// </summary>
/// <param name="type">The type for which to get the property data.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The <see cref="PropertyData"/> of the requested property.</returns>
/// <exception cref="PropertyNotRegisteredException">Thrown when the property is not registered.</exception>
public PropertyData GetPropertyData(Type type, string name)
{
if (!IsPropertyRegistered(type, name))
{
throw new PropertyNotRegisteredException(name, type);
}
lock (_propertyDataLock)
{
return _propertyData[type][name];
}
}
/// <summary>
/// Maps the name of the XML element to a property name.
/// </summary>
/// <param name="type">The type for which to make the xml name.</param>
/// <param name="xmlName">Name of the XML element.</param>
/// <returns>
/// Name of the property that represents the xml value.
/// </returns>
public string MapXmlNameToPropertyName(Type type, string xmlName)
{
InitializeXmlPropertyMappings(type);
return _xmlNameToPropertyNameMappings[type][xmlName];
}
/// <summary>
/// Maps the name of the property name to an XML name.
/// </summary>
/// <param name="type">The type for which to make the xml name.</param>
/// <param name="propertyName">Name of the property.</param>
/// <returns>
/// Name of the XML element that represents the property value.
/// </returns>
public string MapPropertyNameToXmlName(Type type, string propertyName)
{
InitializeXmlPropertyMappings(type);
return _xmlPropertyNameToXmlNameMappings[type][propertyName];
}
/// <summary>
/// Initializes the XML property mappings.
/// </summary>
/// <param name="type">The type for which to initialize the xml mappings.</param>
private void InitializeXmlPropertyMappings(Type type)
{
if (_xmlNameToPropertyNameMappings.ContainsKey(type))
{
return;
}
_xmlNameToPropertyNameMappings.Add(type, new Dictionary<string, string>());
_xmlPropertyNameToXmlNameMappings.Add(type, new Dictionary<string, string>());
foreach (KeyValuePair<string, PropertyData> propertyData in GetProperties(type))
{
PropertyInfo propertyInfo = TypeHelper.GetPropertyInfo(type, propertyData.Key);
XmlElementAttribute xmlElementAttribute;
if (AttributeHelper.TryGetAttribute(propertyInfo, out xmlElementAttribute))
{
_xmlNameToPropertyNameMappings[type].Add(xmlElementAttribute.ElementName, propertyData.Key);
_xmlPropertyNameToXmlNameMappings[type].Add(propertyData.Key, xmlElementAttribute.ElementName);
}
else
{
_xmlNameToPropertyNameMappings[type].Add(propertyData.Key, propertyData.Key);
_xmlPropertyNameToXmlNameMappings[type].Add(propertyData.Key, propertyData.Key);
}
}
}
#endregion
}
}