Daniel Shillcock Daniel Shillcock - 18 days ago 6
Vb.net Question

Dynamically loading Assembly

In the past, I have written an application that dynamically loads a DLL and all of it's dependencies based upon a value in a database, as below (sanitised some parameters)

VB

Dim oType As System.Type
Dim oAssembly As System.Reflection.Assembly
Dim oObject As System.Object
oAssembly = Assembly.LoadFrom(path)
oType = oAssembly.GetType("LogicValidator")
oObject = Activator.CreateInstance(oType)

oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir)
Console.WriteLine("Begin processing...")
oObject.ProcessBatch(cm_uid)


Now, when I write something similar in C#, an error is present before building the application, stating the following:

C#

System.Type oType = default(System.Type);
System.Reflection.Assembly oAssembly = default(System.Reflection.Assembly);
System.Object oObject = null;
oAssembly = Assembly.LoadFrom(path);
oType = oAssembly.GetType("LogicValidator");
oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);


Error

'object' does not contain a definition for 'Initialise' and no extension method 'Initialise' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)


How can my C# application identify that a method does not exist before compiling, if it is loaded at runtime?

Edit

I have struck out the below for the purposes of helping others who stumble across this question. Whilst it does point to the answer, others have answered it more eloquently. :-)

I would like to add, that the below works - but only if the loaded assemblies dependencies are already present.

var DLL = Assembly.LoadFile(path);
Type type = DLL.GetType("LogicValidator");
dynamic c = Activator.CreateInstance(type);
c.Initialise("param1", "param2", "param3", audit, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
c.ProcessBatch(cm_uid);



Answer

If you don't know the type at compile time you can make use of the dynamic runtime by declaring the type to be dynamic:

var oAssembly = Assembly.LoadFrom(path);
var oType = oAssembly.GetType("LogicValidator");
dynamic oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);

However, you might consider an approach where the loaded type implements a known interface (which would be declared in an assembly that is referenced both by the add-in and your code):

public interface IProcessor
{
    void Initialise(
        string param1, 
        string param2, 
        string param2, 
        AuditTail auditTrail, 
        UserInfo userInfo, 
        DirectoryInfo workingDir);

    void ProcessBatch(int uid);
}

You can then create an instance as follows and get full IntelliSense support and type checking:

var oAssembly = Assembly.LoadFrom(path);
var oType = oAssembly.GetType("LogicValidator");
IProcessor oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);