Casting to base class throws InvalidCastException

One of my assemblies contains the following types of "providers":

InheritanceTree

I also have an XML file that contains information about the provider using the base class DeviceInfoProvider

. A simplified version looks like this:

<DeviceInfoProvider Type="SbRioI2CProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>
<DeviceInfoProvider Type="GenericProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>

      

At runtime, I map XML fields to my variables:

assembly.dllassemblyPath
TypetypeName

      

And after reading the XML, use the following code to instantiate my types:

var assembly = Assembly.LoadFrom(assemblyPath);

var type = (from t in assembly.GetTypes()
            where t.IsPublic && t.Name == typeName
            select t).FirstOrDefault();

if (type != null)
{
    instance = type.GetConstructor(Type.EmptyTypes).Invoke(null);
}

      

As expected, this creates my objects appropriately.

The problem comes when I try to use an instance as a base class object:

using (var provider = instance as DeviceInfoProvider)
{
    // provider is null!
}

      

The runtime type instance

is the expected derived class, but I cannot successfully apply it to the base type.

What am I missing?

+3


source to share


2 answers


Perhaps the problem is that you are instantiating (GenericProvider, SbRioI2CProvider) from types in assembly.dll in the context of LoadFrom. Then you try to pass by type (DeviceInfoProvider) in that assembly. This implies the use of the Load context. Types from the same assembly, but loaded in different contexts, are considered different runtime types, so it fails and you get null. This article provides some additional explanation of assembly binding contexts.



To succeed, you have to get Assembly

loaded into the LoadFrom context into the Load context. There are several ways to do this. One way is to install the assembly in the GAC. Another is to remove the .dll collector from the application base so that it will not be detected by probing. Then use the AppDomain.AssemblyResolve event to load Assembly

, which you received via LoadFrom.

+2


source


Calling the constructor of a reflected type does not instantiate it.

To instantiate the reflected type, call Activator.CreateInstance

.

It looks like this line should be:



if (type != null) {
    instance = Activator.CreateInstance(type)
}

      

This will result in being instance

a type object

, but now you can use it for whatever you want.

See: http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

0


source







All Articles