8

我正在尝试编写一个通用方法来XElement以强类型方式获取值。这是我所拥有的:

public static class XElementExtensions
{
    public static XElement GetElement(this XElement xElement, string elementName)
    {
        // Calls xElement.Element(elementName) and returns that xElement (with some validation).
    }

    public static TElementType GetElementValue<TElementType>(this XElement xElement, string elementName)
    {
        XElement element = GetElement(xElement, elementName);
        try
        {
            return (TElementType)((object) element.Value); // First attempt.
        }
        catch (InvalidCastException originalException)
        {
            string exceptionMessage = string.Format("Cannot cast element value '{0}' to type '{1}'.", element.Value,
                typeof(TElementType).Name);
            throw new InvalidCastException(exceptionMessage, originalException);
        }
    }
}

正如您First attempt在行中看到的GetElementValue,我正在尝试从字符串 -> 对象 -> TElementType。不幸的是,这不适用于整数测试用例。运行以下测试时:

[Test]
public void GetElementValueShouldReturnValueOfIntegerElementAsInteger()
{
    const int expectedValue = 5;
    const string elementName = "intProp";
    var xElement = new XElement("name");
    var integerElement = new XElement(elementName) { Value = expectedValue.ToString() };
    xElement.Add(integerElement);

    int value = XElementExtensions.GetElementValue<int>(xElement, elementName);

    Assert.AreEqual(expectedValue, value, "Expected integer value was not returned from element.");
}

GetElementValue<int>调用时出现以下异常:

System.InvalidCastException:无法将元素值“5”转换为“Int32”类型。

我是否必须分别处理每个铸造案例(或至少是数字案例)?

4

5 回答 5

11

你也可以试试Convert.ChangeType

Convert.ChangeType(element.Value, typeof(TElementType))
于 2010-10-07T11:33:20.367 回答
3

从您的代码中,而不是:

return (TElementType)((object) element.Value);

你会这样做:

return (TElementType) Convert.ChangeType(element.Value, typeof (T));

这里唯一需要注意的是 TElementType 必须实现 IConvertible。但是,如果您只是在谈论内在类型,那么它们都已经实现了。

对于您的自定义类型,假设您希望它们在这里,您必须进行自己的转换。

于 2010-10-07T12:44:24.593 回答
2

您不能从Stringto进行隐式或显式强制转换Int32,您需要为此使用Int32'sParseTryParse方法。您可能可以创建一些漂亮的扩展方法,例如:

    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Text;

    /// <summary>
    /// Provides extension methods for strings.
    /// </summary>
    public static class StringExtensions
    {
        #region Methods
        /// <summary>
        /// Converts the specified string to a <see cref="Boolean"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="Boolean"/>.</returns>
        public static bool AsBoolean(this string @string)
        {
            return bool.Parse(@string);
        }

        /// <summary>
        /// Converts the specified string to a <see cref="Boolean"/> using TryParse.
        /// </summary>
        /// <remarks>
        /// If the specified string cannot be parsed, the default value (if valid) or false is returned.
        /// </remarks>
        /// <param name="string">The string to convert.</param>
        /// <param name="default">The default value for if the value cannot be parsed.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static bool AsBooleanNonStrict(this string @string, bool? @default = null)
        {
            bool @bool;
            if ((!string.IsNullOrEmpty(@string)) && bool.TryParse(@string, out @bool))
                return @bool;

            if (@default.HasValue)
                return @default.Value;

            return false;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="DateTime"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static DateTime AsDateTime(this string @string)
        {
            return DateTime.Parse(@string);
        }

        /// <summary>
        /// Converts the specified string to a <see cref="DateTime"/> using TryParse.
        /// </summary>
        /// <remarks>
        /// If the specified string cannot be parsed, <see cref="DateTime.MinValue"/> is returned.
        /// </remarks>
        /// <param name="string">The string to convert.</param>
        /// <param name="default">The default value for if the value cannot be parsed.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static DateTime AsDateTimeNonStrict(this string @string, DateTime? @default = null)
        {
            DateTime datetime;
            if ((!string.IsNullOrEmpty(@string)) && DateTime.TryParse(@string, out datetime))
                return datetime;

            if (@default.HasValue)
                return @default.Value;

            return DateTime.MinValue;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="TEnum"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="TEnum"/>.</returns>
        public static TEnum AsEnum<TEnum>(this string @string) where TEnum : struct
        {
            return (TEnum)Enum.Parse(typeof(TEnum), @string);
        }

        /// <summary>
        /// Converts the specified string to a <see cref="TEnum"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="TEnum"/>.</returns>
        public static TEnum AsEnumNonStrict<TEnum>(this string @string, TEnum @default) where TEnum : struct
        {
            TEnum @enum;
            if ((!string.IsNullOrEmpty(@string)) && Enum.TryParse(@string, out @enum))
                return @enum;

            return @default;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="Int32"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="Int32"/>.</returns>
        public static int AsInteger(this string @string)
        {
            return int.Parse(@string);
        }

        /// <summary>
        /// Converts the specified string to a <see cref="Int32"/> using TryParse.
        /// </summary>
        /// <remarks>
        /// If the specified string cannot be parsed, the default value (if valid) or 0 is returned.
        /// </remarks>
        /// <param name="string">The string to convert.</param>
        /// <param name="default">The default value for if the value cannot be parsed.</param>
        /// <returns>The specified string as a <see cref="Int32"/>.</returns>
        public static int AsIntegerNonStrict(this string @string, int? @default = null)
        {
            int @int;
            if ((!string.IsNullOrEmpty(@string)) && int.TryParse(@string, out @int))
                return @int;

            if (@default.HasValue)
                return @default.Value;

            return 0;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="bool"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static bool? AsNullableBolean(this string @string)
        {
            bool @bool;
            if ((string.IsNullOrEmpty(@string)) || !bool.TryParse(@string, out @bool))
                return null;

            return @bool;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="DateTime"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static DateTime? AsNullableDateTime(this string @string)
        {
            DateTime dateTime;
            if ((string.IsNullOrEmpty(@string)) || !DateTime.TryParse(@string, out dateTime))
                return null;

            return dateTime;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="DateTime"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="DateTime"/>.</returns>
        public static TEnum? AsNullableEnum<TEnum>(this string @string) where TEnum : struct
        {
            TEnum @enum;
            if ((string.IsNullOrEmpty(@string)) || !Enum.TryParse(@string, out @enum))
                return null;

            return @enum;
        }

        /// <summary>
        /// Converts the specified string to a <see cref="Int32"/>
        /// </summary>
        /// <param name="string">The string to convert.</param>
        /// <returns>The specified string as a <see cref="Int32"/>.</returns>
        public static int? AsNullableInteger(this string @string)
        {
            int @int;
            if ((string.IsNullOrEmpty(@string)) || !int.TryParse(@string, out @int))
                return null;

            return @int;
        }
        #endregion
    }

我通常经常使用这些。

于 2010-10-07T11:32:12.730 回答
1

在 C# 中,您不能将字符串对象强制转换为 Int32。例如此代码产生编译错误:

    string a = "123.4";
    int x = (int) a;

如果您需要此类功能,请尝试使用Convert 类Int32.ParseInt32.TryParse方法。
是的,如果要将字符串转换为 int,则应该单独处理数字转换。

于 2010-10-07T11:29:37.990 回答
0

string 还实现了 IConvertible,因此您可以执行以下操作。

((IConvertible)mystring).ToInt32(null);

您甚至可以在它周围抛出一些扩展方法以使其更清洁。

于 2010-10-07T12:40:27.470 回答