Search code examples
c#castingcreateinstance

Error casting object loaded via createInstance


I have an assembly that contains the class RD_ToBeProcessed which inherits from ToBeProcessed. The classes are in separate assemblies.

I load an object using createInstance and then attempt to cast it with the following code:

    private Type tbpType = null;
    public ToBeProcessed getToBeProcessedObject(string data)
    {
        // The data is passed in so that the fields are populated with the
        // correct data.
        if (tbpType==null){
            Assembly assembly = 
                Assembly.LoadFrom("c:\\project\\RD_ToBeProcessed.dll");
            tbpType = assembly.GetType("myNameSpace.RD_ToBeProcessed");
        }
        Object tbp = Activator.CreateInstance(tbpType,data);
                    // This line throws an error
        return (ToBeProcessed)tbp;
    }

This is a repeat of the question .NET: Unable to cast object to interface it implements but I don't know how to resolve it.

The error thrown is

Unable to cast object of type 'myNameSpace.RD_ToBeProcessed' to type 'myNameSpace.ToBeProcessed'.

The accepted answer indicated that the problem was 2 different versions of the base assembly. But I have used ILSpy and both the ToBeProcessed dlls in the application directory and the one in the same directory as RD_ToBeProcessed report:

ToBeProcessed, Version=1.0.4336.31676, Culture=neutral, PublicKeyToken=null

So I am not sure what I am doing wrong. Should I change ToBeProcessed to be an interface (ItoBeProcessed) that is used in the app and the plugin? Then have a separate assembly that holds the base ToBeProcessed class which would not be referenced by the application at all (just the by plugin)?

EDIT: The problem was resolved by using an interface class. I still don't know what was going wrong but Kol's answer showed that in theory this should have worked correctly the way it was.


Solution

  • The following solution compiles and runs without error:

    Assembly #1: ToBeProcessed

    Compiled to DLL, which is copied to c:\project and c:\project\test. Refers to System.dll. ToBeProcessed.cs:

    using System;
    using System.Reflection;
    
    [assembly: AssemblyVersion("1.0.*")]
    
    namespace myNameSpace
    {
      public class ToBeProcessed
      {
        protected string data;
        public ToBeProcessed() { }
        public string Process() { return data.ToUpper(); }
      }
    }
    

    Assembly #2: RD_ToBeProcessed

    Compiled to DLL, which is copied to c:\project. Refers to System.dll and ToBeProcessed.dll. RD_ToBeProcessed.cs:

    using System;
    using System.Reflection;
    
    [assembly: AssemblyVersion("1.0.*")]
    
    namespace myNameSpace
    {
      public class RD_ToBeProcessed : ToBeProcessed
      {
        public RD_ToBeProcessed(string data) { this.data = data; }
      }
    }
    

    Assembly #3: ToBeProcessedTest

    Compiled to EXE, which is copied to c:\project\test. Refers to System.dll and ToBeProcessed.dll. ToBeProcessedTest.cs:

    using System;
    using System.Reflection;
    
    [assembly: AssemblyVersion("1.0.*")]
    
    namespace myNameSpace
    {
      class ToBeProcessedTest
      {
        private Type tbpType = null;
        public ToBeProcessed getToBeProcessedObject(string data)
        {
          if (tbpType == null)
          {
            Assembly assembly = Assembly.LoadFrom("c:\\project\\RD_ToBeProcessed.dll");
            tbpType = assembly.GetType("myNameSpace.RD_ToBeProcessed");
          }
          Object tbp = Activator.CreateInstance(tbpType, data);
          return (ToBeProcessed)tbp;
        }
    
        public static void Main()
        {
          ToBeProcessedTest test = new ToBeProcessedTest();
          ToBeProcessed tbp1 = test.getToBeProcessedObject("myData1");
          Console.WriteLine(tbp1.Process());
          ToBeProcessed tbp2 = test.getToBeProcessedObject("myData2");
          Console.WriteLine(tbp2.Process());
          Console.ReadKey(true);
        }
      }
    }
    

    Output:

    MYDATA1
    MYDATA2