views:

336

answers:

3

I have a class:

public abstract class SendAgencyFileComponent : ISendAgencyFileComponent
{
    public AgencyOutput agencyOutput;
    public TDXDataTypes.DB.Entity client;
    public TDXDataTypes.DB.Entity agency;

    public SendAgencyFileComponent(AgencyOutput agencyOutput, TDXDataTypes.DB.Entity client, TDXDataTypes.DB.Entity agency)
    {
        this.agencyOutput = agencyOutput;
        this.client = client;
        this.agency = agency;
    }
}

I have a number of classes that inherit from this class, that reside in various DLLs (including the one this is being called from, but in a different location). I need to be able to instantiate an instance of this class from the DLL location and class name. Currently I am using:

System.Reflection.Assembly assembly = 
   System.Reflection.Assembly.LoadFrom(
   "C:\\Program Files\\RMIS\\" + format.AssemblyName + ".dll");

return assembly.CreateInstance(
   format.ClassName, 
   true, 
   System.Reflection.BindingFlags.CreateInstance, 
   null, 
   new Object[] { agencyOutput, client, agency }, 
   System.Globalization.CultureInfo.CurrentCulture, 
   null
   ) as DotNet_WS_Components.ISendAgencyFileComponent;

But I keep getting the error:

Constructor on type 'TDXDataTypes.DotNet_WS_Components.InternationalAgencyFileOut' not found.

I'm sure my arguments match the constructor perfectly, and when loading the class from the same assembly using Activator.CreateInstance, it works fine:

System.Runtime.Remoting.ObjectHandle sendFilehandle = 
   Activator.CreateInstance(
       format.AssemblyName, 
       format.ClassName, 
       true, 
       System.Reflection.BindingFlags.CreateInstance, 
       null,
       new Object[] { agencyOutput, client, agency }, 
       System.Globalization.CultureInfo.CurrentCulture, 
       null, 
       null);

       return (TDXDataTypes.DotNet_WS_Components.ISendAgencyFileComponent)sendFilehandle.Unwrap();

The particular example I'm working on at the moment is:

Webservice
-> calls TDXDataTypes dll method through referenced DLL
-> calls TDXDataTypes dll class (above) using reflection from a different folder
A: 

What does the constructor (or constructors) of TDXDataTypes.DotNet_WS_Components.InternationalAgencyFileOut look like? It almost sounds as if there is no contructor accepting the three arguments that you pass. Are they of the same types as the expected arguments in the constructor of the class?

Update

Regarding your second code sample; you have a rather different set of BindingFlags in the two examples. The failing one specifies BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, while the working one uses only BindingFlags.CreateInstance. Could it be this difference that causes one to fail and one to succeed?

Fredrik Mörk
The constructor is exactly the same as the one for SendAgencyFileComponent
ck
I would guess the same thing. Should double check the assembly and the name and make sure you are callin gwhat you expect.
David Basarab
@David - it works fine using Activator.CreateInstance using almost exactly the same method paramters (I'll add this example to the question), so I'm sure it's something to do with the remote DLL.
ck
And the constructor is public? (just double/triple checking)
Fredrik Mörk
Yes, constructor is public, on both the abstract class and inheriting class.
ck
@ck: then I agree that we can probably rule out constructor mismatch.
Fredrik Mörk
I've tried lots of combinations, including making sure both were the same at the point one of them was working. How they are now was my last try.
ck
@ck: bummer. Really annoying kind of problem.
Fredrik Mörk
Thanks for trying:) I'm hoping jon Skeet will turn up and save the day...
ck
A: 

Since your bindingflags deviate in the two examples your giving and since getting them wrong will give you the stated exception Im guessing that's your problem.

UPDATE: If that's not the acse I'd compare the assembly versions

System.Reflection.Assembly assembly = 
   System.Reflection.Assembly.LoadFrom(
   "C:\\Program Files\\RMIS\\" + format.AssemblyName + ".dll");

might not return the same version of the assembly (or even the same assembly) that the call to Activator is using so there's a potential risk that the type definition differs.

Try dumping the value of format.ClassName, assembly name/version/culture/key-hash (from the call to LoadFrom) and obj.GetType().AssemblyQualifiedName of the ISendAgencyFileComponent object you can create and compare

Rune FS
I've tried lots of comniations of binding flags, including having the same on both calls with one version working and the other not working.
ck
The assembly version *could* be the problem, but I remember deploying the same build to both locations to see if that worked. I have a workaround now, but thanks for your help.
ck
A: 

I managed to get this working with a simple workaround.

For any calls to the classes within the same assembly, I use the Activator.CreateInstance, and for any calls to a different DLL, I use the other method.

ck