3

我的 web.config 中有以下节点

<parameter value="100" type="System.Int64, mscorlib" />

读入以下 ConfigurationProperty

public class ParameterElement : ConfigurationElement
{
    [ConfigurationProperty("type", IsRequired = false, DefaultValue = "System.String, mscorlib")]
    [TypeConverter(typeof (TypeNameConverter))]
    public Type Type
    {
        get { return (Type) this["type"]; }
        set { this["type"] = value; }
    }

    [ConfigurationProperty("value", IsRequired = true)]
    public object Value
    {
        get { return ... ? }
        set { this["value"] = value; }
    }
}

这正确地建立了我在节点上设置的类型,但是我怎样才能返回该类型的值?我尝试过的所有内容都返回以下异常:

找不到支持“对象”类型的属性“值”转换为/从字符串转换的转换器。

4

1 回答 1

0

可能为时已晚,但我有同样的需求,我找到了解决方案。

首先,您需要在 Value 上添加一个 TypeConverter 来反序列化配置,我选择 StringConverter 但我们可以实现 XMLConverter 或 JSONConverter。

二、必须解析字符串,xml或者json

[TypeConverter(typeof(StringConverter))]
[ConfigurationProperty(ValueKey, IsRequired = true)]
public object Value
{
    get { return this[ValueKey].ConvertTo(this.Type); }
    set { this[ValueKey] = value; }
}

这是我解析字符串的扩展方法

/// <summary>
/// Convert an object to a specific type with a support of string parsing if needed
/// </summary>
/// <param name="input">Object to convert</param>
/// <param name="type">Type of converted object</param>
/// <returns>Object converted</returns>
public static object ConvertTo(this object input, Type type)
{
    object returnValue;
    try
    {
        // Try change type
        returnValue = System.Convert.ChangeType(input, type);
    }
    catch(Exception exception)
    {
        if(exception is InvalidCastException || exception is FormatException)
        {
            // Try to parse because the cast is invalid
            // If the type is an enumeration
            if(type.IsEnum)
            {
                // Try to parse the string
                try { returnValue = Enum.Parse(type, input.ToString(), true); }
                catch(Exception) { returnValue = System.Convert.ChangeType(input, typeof(int)); }
            }
            else if(type.IsNullable())
            {
                // If the type is a nullable type (int?,long?,double?....)
                returnValue = input == null ? null : System.Convert.ChangeType(input, Nullable.GetUnderlyingType(type));
            }
            else if(input is string || input == null)
            {
                // If the original type is string, we try to parse : if parsing failed then return value is the default value of the type
                if(!((string)input).TryParse(type, out returnValue))
                {
                    // Conversion "1" to true is not supported by previous case, so if return type is boolean try to convert "1" to true
                    if(type == typeof(Boolean))
                        returnValue = ((string)input).ToBoolean();
                }
            }
            else
                throw new InvalidCastException(String.Format("Unable to cast \"{0}\" in {1}", input, type.Name));
        }
        else
            throw;
    }
    // return the value converted
    return returnValue;
}

/// <summary>
/// Try to parse a string
/// </summary>
/// <param name="text">Text to parse</param>
/// <param name="type">Type of result</param>
/// <param name="result">Result</param>
/// <returns>True if string was parsed, else false</returns>
public static bool TryParse(this string text, Type type, out object result)
{
    // Get specific converter for the type
    TypeConverter converter = TypeDescriptor.GetConverter(type);
    // If there is a converter and conversion is valid
    if(converter != null && converter.IsValid(text))
    {
        // Convert
        result = converter.ConvertFromInvariantString(text);
        return true;
    }
    else
    {
        // Return the default value of the type
        result = type.GetDefaultValue();
        return false;
    }
}

/// <summary>
/// Get the default value of a type
/// </summary>
/// <param name="type">Type</param>
/// <returns>Default value</returns>
public static object GetDefaultValue(this Type type)
{
    return type.IsValueType ? Activator.CreateInstance(type) : null;
}

/// <summary>
/// Define if a type is a nullable type (int?, long?, double?...)
/// </summary>
/// <param name="type">Type</param>
/// <returns>true if the type is a nullable type</returns>
public static bool IsNullable(this Type type)
{
    return (!type.IsGenericType) ? false : type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
}
于 2016-11-21T08:15:35.300 回答