How to Cast to Generic Parameter in C#?

Doctor Blue picture Doctor Blue · Oct 7, 2010 · Viewed 7.3k times · Source

I'm trying to write a generic method for fetching an XElement value in a strongly-typed fashion. Here's what I have:

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);
        }
    }
}

As you can see on the First attempt line of GetElementValue, I'm trying to go from string -> object -> TElementType. Unfortunately, this does not work for an integer test case. When running the following test:

[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.");
}

I get the following exception when GetElementValue<int> is called:

System.InvalidCastException : Cannot cast element value '5' to type 'Int32'.

Am I going to have to handle each casting case (or at least the numeric ones) separately?

Answer

Patko picture Patko · Oct 7, 2010

You could also try the Convert.ChangeType

Convert.ChangeType(element.Value, typeof(TElementType))