Let's say I have 3 DLLs (BlueCar, RedCar, YellowCar) that each have a named class (BlueCarClass, etc) that also all implement the same interface, Car, and are all built from the same namespace (Car_Choices). So a DLL looks something like this before compiled:
namespace Car_Choices
{
public interface Car
{
void What_Color();
}
public class BlueCarClass : Car
{
public void What_Color()
{
MessageBox.Show('The color is blue.');
}
}
}
And the DLL's name would be "BlueCar.dll".
In the main program, the user selects which ever car color they want, and based on their choice it dynamically loads only the appropriate DLL and runs What_Color(). The main program has a copy of the Car interface. Right now I have the following, but it's not working.
static void Main()
{
string car_choice = win_form_list.ToArray()[0]; //gets choice from a drop down
Assembly car_assembly = Assembly.Load(car_choice); //car_choice is BlueCar
Type car_type = car_assembly.GetType("Car");
Car car = Activator.CreateInstance(type) as Car;
car.What_Color();
}
I've also tried
static void Main()
{
string car_choice = win_form_list.ToArray()[0]; //gets choice from a drop down
ObjectHandle car_handle = Activator.CreateInstance(assembly_name, "Car_Choices."+ car_choice);
Car car= (Car)handle.Unwrap();
car.What_Color();
}
Any help? Are there structural changes I need to make (such as putting each car color DLL in it's own namespace)? Or am I not understanding how to load and use classes from DLLs appropriately.
EDIT: Here's the solution that I got to work, in case anyone is looking for a more detailed answer.
PROJECT 1: The shared interface (as a Class library) Car_Interface.cs
namespace Car_Interface
{
public interface ICar_Interface
{
char Start_Car();
}
}
Compile into Car_Interface.dll, reference DLL in next 2 projects.
PROJECT 2: Car interface implementation, as a class library BlueCar.cs
namespace BlueCar_PlugIn
{
public class BlueCar : Car_Interface.ICar_Interface
{
public char Start_Car()
{
MessageBox.Show("Car is started");
}
}
}
Compile into BlueCar_PlugIn.dll
PROJECT 3: Main program/driver Program.cs
namespace Main_Program
{
public class Program
{
static void Main()
{
Assembly assembly = Assembly.Load(DLL_name); //Where DLL_name is the DLL you want to load, such as BlueCar_PlugIn.dll
Type type = (Type)assembly.GetTypes().GetValue(0); //Class that implements the interface should be first. A resource type could also possibly be found
//OR
Type type = (Type)assembly.GetType(DLL_name + class_name); //In this case, BlueCar_PlugIn.BlueCar
Car_Interface.ICar_Interface new_car = (Car_Interface.ICar_Interface)Activator.CreateInstance(type);
new_car.Start_Car();
}
}
}
Now if you move both DLLs into bin (or where ever your program is compiled to) and run it, it'll be able to dynamically load BlueCar_PlugIn.dll but not neccessarily need it to run (ex, if you have YellowCar_PlugIn.dll and also RedCar_PlugIn.dll with similar implementations, only one will need to be loaded for the program to work).
Your code does not work because, for example, BlueCarClass does not implement Car that is in the application assembly because the fully qualified name of base classes are different. The class Car that is in your BlueCar assembly may have fully qualified name
BlueCar.Car, BlueCar, Version=1.0.0.0, Culture=neutral, PublicKey=null
but the class Car that is in your application has different fully qualified name, something like this
SomeApp.Car, SomeApp, Version=1.0.0.0, Culture=neutral, PublicKey=null
Even though you put the class to the same namespace, the full name is still different because it include assembly name.
There are many ways of how to achieve results that you want: you can use MEF or you can create something more lightweight by yourself.
Your solution needs to have at least 3 assemblies:
PS Actually you can do this using 2 assemblies by merging #1 and #3 and make #2 reference #3 instead of #1. It will work, however its logically incorrect because you introduce cross references (implicitly). In my opinion this approach smells.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With