How do you create an instance of an object that is not included in your C # project?

Note. The entire sample code is greatly simplified.

I have a DLL defined as:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Web; namespace RIV.Module { public interface IModule { StringWriter ProcessRequest(HttpContext context); string Decrypt(string interactive); string ExecutePlayerAction(object ParamObjectFromFlash); void LogEvent(object LoggingObjectFromFlash); } } 

Now, outside my solution, other developers can define specific classes and transfer them to the BIN folder of my application. Maybe something like:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using RIV.Module; namespace RIV.Module.Greeting { public class Module : IModule { public System.IO.StringWriter ProcessRequest(System.Web.HttpContext context) { //... } public string Decrypt(string interactive) { //... } public string ExecutePlayerAction(object ParamObjectFromFlash) { //... } public void LogEvent(object LoggingObjectFromFlash) { //... } } } 

Now, in my application, I would need to know that a new module is available (I guess through web.config or something like that), and then you can call it based on some kind of trigger in the Database Campaign table (which maps to the module that will be used for this particular campaign).

I am trying to create it this way:

 var type = typeof(RIV.Module.Greeting.Module); var obj = (RIV.Module.Greeting.Module)Activator.CreateInstance(type); 

However, the compiler spews because the link was never installed on RIV.Module.Greeting.dll !

What am I doing wrong?

+4
source share
2 answers

Instead of typeof (RIV.Module.Greeting.Module) try using

 var type = Type.GetType("RIV.Module.Greeting.Module, RIV.Module.Greeting"); 

(i.e. load the type by specifying its name assigned to the class as a string) and listing in the IModule.

This approach requires you to know the exact class names and module assemblies (as you wrote, they can be stored in web.config).

Alternatively, you can use a fully dynamic approach to the plugin:

  • establish an agreement that all module assemblies should be named "RIV.Module.XYZ"
  • scan bin directory for dll matching
  • for each DLL, load it (e.g. Assembly.Load) and scan for types that implement IModule
  • create all found types and apply to IModule
+1
source

You need to use more reflections:

  • Download the assembly by calling Assembly.Load
  • Find the type by calling someAssembly.GetType(name) or by searching for someAssembly.GetTypes()
  • Pass the Type instance to Activator.CreateInstance
  • Pass it to your interface.
+2
source

Source: https://habr.com/ru/post/1338959/


All Articles