5

I have the following scenario where I get a string that looks as follows

"System.DateTime?"

or

"int?"

What I would like to be able to do, is retrieve the System.Type for that string which would look like:

{Name = "Nullable1" FullName = "System.Nullable1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

Now I know how to retrieve the type from a string I can just say Type.GetType("System.DateTime") when dealing with non nullable type or typeof(DateTime?) when I know it's going to be DateTime nullable, but in this instance I'm unaware of the what nullable type might come through and will only receive it as string.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
Domitius
  • 475
  • 6
  • 17
  • I'm going to guess it would be `Nullable`. – gunr2171 Feb 13 '18 at 18:39
  • What's generating that string, and why isn't it generating a proper name for the type? – Servy Feb 13 '18 at 18:41
  • See also / maybe duplicate of https://stackoverflow.com/questions/20659801/typeofdatetime-name-nullable1 – gunr2171 Feb 13 '18 at 18:41
  • @gunr2171 They have a string, not a `Type`, so that post doesn't really help. They also don't need the underlying type, they want the `Nullable` `Type` value. – Servy Feb 13 '18 at 18:42
  • Do you need to support **any** string that might name a legal type in .NET or do you have a limited subset of things you need to support? I ask because ... do you need to support **this** string? `"Namespace1.Namespace2.Generic.Nested.Inner.NestedInner"` ? – Lasse V. Karlsen Feb 13 '18 at 20:13

3 Answers3

5

I'm missing part of the context - for example, does the string always represent a nullable value type?

Given that you can extract the value type name from the string and create a reference to that type:

var valueType = Type.GetType("System.DateTime");
var nullableType = typeof(Nullable<>).MakeGenericType(valueType);

That should solve part of the problem. The harder part will be determining the underlying type from the string, which depends on what sort of inputs you're receiving. It's easy to get a type from System.DateTime, but harder from int. This answer may help with that part.


As far as the input - is there any option that you could provide a list of available choices to the user so that input you receive would always be a valid type name? That would negate the need for any of this. Then you could just do Type.GetType(stringWithTypeName).

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
5

In addition to Scott's answer, you could also use the Type.GetType with the correct name:

System.Nullable`1[System.DateTime]

So this function will get back the correct type for you.

public Type GetType(string typeString)
{
    if (typeString.EndsWith("?"))
    {
        typeString = $"System.Nullable`1[{typeString.TrimEnd('?')}]";
    }
    return Type.GetType(typeString);
}
Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27
  • Or just `typeString.TrimEnd('?')`. I was originally going to include this part, but I was a little confused by the input. It works if it's reliably a type name, but not if it's an alias like `int` or missing the namespace. I'm sure there are ways to work around it, but the intent seems unclear. – Scott Hannen Feb 13 '18 at 19:09
  • Yes... `TrimEnd` sounds better. slipped my mind. thanks. Regarding the aliases, like you said, it won't work and jon skeet gave a good "copy/paste" dictionary(in the link you've provided) that the OP can use. – Ofir Winegarten Feb 13 '18 at 19:15
1

One way to solve this is by creating an extension method for type "Type" and make the implementation of that method to check if it is a nullable type and return the right type. follows example:

namespace ExtensionMethod  
    {
        public static class MyExtensions
        {
            public static Type GetNullabeType(this Type t, string typeName)
            {
                string typeString = typeName;
                var typeNonNullabe = Type.GetType(typeString.Replace("?", ""));
                if (typeString.Contains("?") && typeNonNullabe != null)
                {
                    return typeof(Nullable<>).MakeGenericType(typeNonNullabe);
                }
                return t;
            }
        }
    }

after that, just use this extension method as follows:

Type t = null;
var type = t.GetNullabeType("System.DateTime?");