Search code examples
objecttypesinstance

How to convert object returned by Activator.CreateInstance to the type it converted?


In the code below, is it possible to convert x to the type you're passing into Activator.CreateInstance without knowing what it is ahead of time? I tried passing in typeof...but that doesn't work.

var testClasses = AppDomain.CurrentDomain.GetAssemblies()
                  .Single(a=>a.FullName.StartsWith("VerifyStuff")).GetTypes()
                  .Where(t=>t.UnderlyingSystemType.Name.StartsWith("VerifyXXX"));

var x = Activator.CreateInstance(testClasses.ElementAt(0));

Thanks!


Solution

  • You simply need to cast it:

    MyObject x = (MyObject) Activator.CreateInstance(testClasses.ElementAt(0));
    

    of course this is going to be more difficult if you have a whole range of types in testClasses. If they are all derived from the same base class or implement the same interface then you can cast to that base class or interface.

    Edit:

    is it possible to convert x to the type you're passing into Activator.CreateInstance without knowing what it is ahead of time?

    just to be a little more explanatory: x is of the type you passed in to CreateInstance, but it is cast as an object, because CreateInstance has no idea what you may throw at it. You problem occurs after you've created your concrete instance - you can't pass it into another (strongly typed) function because you have it as an object. There are a couple of ways around this:

    • as i mentioned above, have them all derive from the same base class or interface, so that you can pass them around as that base class or interface type

    • if you have a function that needs to perform an operation on those concrete instances, create a generic function to do it:

      
      public T MyFunc(T myConcreteInstance) 
      {
          ... do whatever it is i need to do...
      }
      
    • this is ugly, but it may be difficult to avoid... use a big if..else if statement to determine their types before operating on them (hint: to avoid this use option #1 above...):

      
      Type t = myConcreteInstance.GetType();
      if (t == typeof(someType1))
      {
      
      }
      else if (t == typeof(someType2))
      {
      
      }
      ... etc ...
      

    If at this point you are thinking "why don't i just make a generic version of CreateInstance()?" then don't bother - there already is one, it still doesn't solve your issue of having things strongly typed before passing them around. To quote MSDN:

    In general, there is no use for the CreateInstance in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used (new operator in C#, New in Visual Basic, gcnew in C++).

    If you are going to use CreateInstance, it's because you don't know the type ahead of time, therefore you must work around it.