#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you 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. // #endregion using System; using System.Globalization; using System.Reflection; using System.Collections; namespace log4net.Util.TypeConverters { /// /// Register of type converters for specific types. /// /// /// /// Maintains a registry of type converters used to convert between /// types. /// /// /// Use the and /// methods to register new converters. /// The and methods /// lookup appropriate converters to use. /// /// /// /// /// Nicko Cadell /// Gert Driesen public sealed class ConverterRegistry { #region Private Constructors /// /// Private constructor /// /// /// Initializes a new instance of the class. /// private ConverterRegistry() { } #endregion Private Constructors #region Static Constructor /// /// Static constructor. /// /// /// /// This constructor defines the intrinsic type converters. /// /// static ConverterRegistry() { // Add predefined converters here AddConverter(typeof(bool), typeof(BooleanConverter)); AddConverter(typeof(System.Text.Encoding), typeof(EncodingConverter)); AddConverter(typeof(System.Type), typeof(TypeConverter)); AddConverter(typeof(log4net.Layout.PatternLayout), typeof(PatternLayoutConverter)); AddConverter(typeof(log4net.Util.PatternString), typeof(PatternStringConverter)); AddConverter(typeof(System.Net.IPAddress), typeof(IPAddressConverter)); } #endregion Static Constructor #region Public Static Methods /// /// Adds a converter for a specific type. /// /// The type being converted to. /// The type converter to use to convert to the destination type. /// /// /// Adds a converter instance for a specific type. /// /// public static void AddConverter(Type destinationType, object converter) { if (destinationType != null && converter != null) { lock(s_type2converter) { s_type2converter[destinationType] = converter; } } } /// /// Adds a converter for a specific type. /// /// The type being converted to. /// The type of the type converter to use to convert to the destination type. /// /// /// Adds a converter for a specific type. /// /// public static void AddConverter(Type destinationType, Type converterType) { AddConverter(destinationType, CreateConverterInstance(converterType)); } /// /// Gets the type converter to use to convert values to the destination type. /// /// The type being converted from. /// The type being converted to. /// /// The type converter instance to use for type conversions or null /// if no type converter is found. /// /// /// /// Gets the type converter to use to convert values to the destination type. /// /// public static IConvertTo GetConvertTo(Type sourceType, Type destinationType) { // TODO: Support inheriting type converters. // i.e. getting a type converter for a base of sourceType // TODO: Is destinationType required? We don't use it for anything. lock(s_type2converter) { // Lookup in the static registry IConvertTo converter = s_type2converter[sourceType] as IConvertTo; if (converter == null) { // Lookup using attributes converter = GetConverterFromAttribute(sourceType) as IConvertTo; if (converter != null) { // Store in registry s_type2converter[sourceType] = converter; } } return converter; } } /// /// Gets the type converter to use to convert values to the destination type. /// /// The type being converted to. /// /// The type converter instance to use for type conversions or null /// if no type converter is found. /// /// /// /// Gets the type converter to use to convert values to the destination type. /// /// public static IConvertFrom GetConvertFrom(Type destinationType) { // TODO: Support inheriting type converters. // i.e. getting a type converter for a base of destinationType lock(s_type2converter) { // Lookup in the static registry IConvertFrom converter = s_type2converter[destinationType] as IConvertFrom; if (converter == null) { // Lookup using attributes converter = GetConverterFromAttribute(destinationType) as IConvertFrom; if (converter != null) { // Store in registry s_type2converter[destinationType] = converter; } } return converter; } } /// /// Lookups the type converter to use as specified by the attributes on the /// destination type. /// /// The type being converted to. /// /// The type converter instance to use for type conversions or null /// if no type converter is found. /// private static object GetConverterFromAttribute(Type destinationType) { // Look for an attribute on the destination type object[] attributes = destinationType.GetCustomAttributes(typeof(TypeConverterAttribute), true); if (attributes != null && attributes.Length > 0) { TypeConverterAttribute tcAttr = attributes[0] as TypeConverterAttribute; if (tcAttr != null) { Type converterType = SystemInfo.GetTypeFromString(destinationType, tcAttr.ConverterTypeName, false, true); return CreateConverterInstance(converterType); } } // Not found converter using attributes return null; } /// /// Creates the instance of the type converter. /// /// The type of the type converter. /// /// The type converter instance to use for type conversions or null /// if no type converter is found. /// /// /// /// The type specified for the type converter must implement /// the or interfaces /// and must have a public default (no argument) constructor. /// /// private static object CreateConverterInstance(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType", "CreateConverterInstance cannot create instance, converterType is null"); } // Check type is a converter if (typeof(IConvertFrom).IsAssignableFrom(converterType) || typeof(IConvertTo).IsAssignableFrom(converterType)) { try { // Create the type converter return Activator.CreateInstance(converterType); } catch(Exception ex) { LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], Exception in call to Activator.CreateInstance", ex); } } else { LogLog.Error(declaringType, "Cannot CreateConverterInstance of type ["+converterType.FullName+"], type does not implement IConvertFrom or IConvertTo"); } return null; } #endregion Public Static Methods #region Private Static Fields /// /// The fully qualified type of the ConverterRegistry class. /// /// /// Used by the internal logger to record the Type of the /// log message. /// private readonly static Type declaringType = typeof(ConverterRegistry); /// /// Mapping from to type converter. /// private static Hashtable s_type2converter = new Hashtable(); #endregion } }