New cast exception with VS2010/.Net 4

Posted by Trevor on Stack Overflow See other posts from Stack Overflow or by Trevor
Published on 2010-05-25T11:53:10Z Indexed on 2010/05/25 14:01 UTC
Read the original article Hit count: 268

Filed under:
|
|

[ Updated 25 May 2010 ] I've recently upgraded from VS2008 to VS2010, and at the same time upgraded to .Net 4.

I've recompiled an existing solution of mine and I'm encountering a Cast exception I did not have before.

The structure of the code is simple (although the actual implementation somewhat more complicated).

Basically I have:

public class SomeClass : ISomeClass
{
 // Stuff
}

public static class ClassFactory
{
  public static IInterface GetClassInstance<IInterface>(Type classType)
  {
     return (IInterface)Activator.CreateInstance(classType); // This throws a cast exception
  }
}

// Call the factory with:

ISomeClass anInstance = ClassFactory.GetClassInstance<ISomeClass>(typeof(SomeClass));

Ignore the 'sensibleness' of the above - its provides just a representation of the issue rather than the specifics of what I'm doing (e.g. constructor parameters have been removed).

The marked line throws the exception:

Unable to cast object of type 'Namespace.SomeClass' to type 'Namespace.ISomeClass'.

I suspect it may have something to do with the additional DotNet security (and in particular, explicit loading of assemblies, as this is something my app does).

The reason I suspect this is that I have had to add to the config file the setting:

<runtime>
    <loadFromRemoteSources enabled="true" />
</runtime>

.. but I'm unsure if this is related.

Update

I see (from comments) that my basic code does not reproduce the issue by itself. Not surprising I suppose. It's going to be tricky to identify which part of a largish 3-tier CQS system is relevant to this problem.

One issue might be that there are multiple assemblies involved. My static class is actually a factory provider, and the 'SomeClass' is a class factory (relevant in that the factories are 'registered' within the app via explicit assembly/type loading - see below) .

Upfront I use reflection to 'register' all factories (i.e. classes that implement a particular interface) and that I do this when the app starts by identifying the relevant assemblies, loading them and adding them to a cache using (in essence):

Loop over (file in files)
{
    Assembly assembly = Assembly.LoadFile(file);
    baseAssemblyList.Add(assembly);
}

Then I cache the available types in these assemblies with:

foreach (Assembly assembly in _loadedAssemblyList)
{
  Type[] assemblyTypes = assembly.GetTypes();
  _loadedTypesCache.AddRange(assemblyTypes);
}

And then I use this cache to do a variety of reflection operations, including 'registering' of factories, which involves looping through all loaded (cached) types and finding those that implement the (base) Factory interface.

I've experienced what may be a similar problem in the past (.Net 3.5, so not exactly the same) with an architecture that involved dynamically creating classes on the server and streaming the compiled binary of those classes to the client app. The problem came when trying to deserialize an instance of the dynamic class on the client from a remote call: the exception said the class type was not know, even though the source and destination types were exactly the same name (including namespace). Basically the cross boundry versions of the class were not recognised as being the same. I solved that by intercepting the deserialization process and explicitly defining the deseriazation class type in the context of the local assemblies.

This experience is what makes me think the types are considered mismatched because (somehow) the interface of the actual SomeClass object, and the interface of passed into the Generic method are not considered the same type.

So (possibly) my question for those more knowledgable about C#/DotNet is: How does the class loading work that somehow my app thinks there are two versions/types of the interface type and how can I fit that?

[ whew ... anyone who got here is quite patient .. thanks ]

© Stack Overflow or respective owner

Related posts about c#

Related posts about .net-4.0