views:

866

answers:

5

I have a class (TabControlH60) that both inherits from a base class (UserControl) and implements an interface (IFrameworkClient). I instantiate the object using the .NET Activator class. With the returned instance, I can cast to the UserControl base class, but not to the interface. The exception I get is below the code snipet. How do I cast to the interface?

object obj = Activator.CreateInstance(objType);
Type[] interfaces = obj.GetType().GetInterfaces(); // contains IFrameworkClient

m_Client = (UserControl)obj;                 // base class cast works
IFrameworkClient fc = (IFrameworkClient)obj; // interface cast fails

// Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window.
{"Unable to cast object of type 'FPG.H60.AFF.TabControlH60' to type 
    'FPG.AFF.Interfaces.IFrameworkClient'."}
A: 

Use the as operator :)

...
m_Client = obj as IFrameworkClient;
if (m_Client != null)  //Remember to check for null in case the cast fails
   ...
...
cwap
After re-reading your question, I don't think this was what you wanted. Sorry :)
cwap
The "as" operator is exactly what you *don't* want to use when debugging casting errors (it silently swallows exceptions, leaving you no easy way to debug why the cast failed)
ckarras
A: 

The cast isn't working because you're trying to cast from type object to the interface. If you replace the interface cast line with:

IFrameworkClient fc = (IFrameworkClient)m_Client;

It will work.

Alternately, I'm mildly certain that you could do the cast from the object to the interface with the as operator.

See this article for more information: http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

One more piece of the puzzle. Interfaces do not derive from object: http://blogs.msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx

Kennet Belenky
`m_Client` and `obj` are almost certainly the same object (unless a conversion is defined). I don't expect this to matter...
Marc Gravell
It doesn't. My test works.
Will
+4  A: 

The most likely cause here is that IFrameworkClient is from a different assembly in the two cases, and is thus a different .NET type. Even if it is the same code, it can be a different type.

Check the AssemblyQualifiedName. Note also that if you are loading this assembly with reflection you can get a different type even with the same AssemblyQualifiedName, thanks to the load-context.

Marc Gravell
That was my first thought too.
bruno conde
That's one possibility, definitely. Mistaken reference. But something like this usually works when debugging and doesn't work when deployed (different assembly at deployment time). Whenever this has happened to me its because Activator.CreateInstance doesn't proactively load all assemblies associated with a type it instantiates.
Will
A: 

If the class FPG.H60.AFF.TabControlH60 actually does implement IFrameworkClient there should be no reason this would fail. The only thing I can think of that causes this exception is if the assembly that contains IFrameworkClient is strongly named and the Tab Control object happens to reference a different version of the containing assembly or your are using a different interface with the name IFrameworkClient.

siz
+2  A: 

Something tells me your sample code is leaving some stuff out...

class Program
{
    static void Main(string[] args)
    {
        var type = typeof(MyClass);
        object obj = Activator.CreateInstance(type);
        Type[] interfaces = obj.GetType().GetInterfaces();

        var m_Client = (UserControl)obj;          
        IFrameworkClient fc = (IFrameworkClient)obj;
    }
}

public interface IFrameworkClient { }

public class UserControl { }

public class MyClass : UserControl, IFrameworkClient { }

This compiles and runs.

I'm betting that the DLL containing the definition of IFrameworkClient hasn't yet been loaded before you try to cast. This can happen when you're using Activator.CreateInstance.

Try inserting var forceLoad = typeof(IFrameworkClient); before the cast.

Will