简体   繁体   中英

How do you instantiate an object that is not included in your C# project?

Note: All 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 of my solution, other developers can define concrete classes and drop them into the BIN folder of my app. 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 app I would need to know that a new Module was available (I am guessing via web.config or something along those lines) and then be able to call it based off of some trigger in the database Campaign table (which maps to the module to use for that specific campaign).

I am trying to instantiate it this way:

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

However, the compiler belches because a reference was never set to RIV.Module.Greeting.dll !

What am I doing wrong?

You need to use more reflection:

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

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

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

(ie load the type by specifying its assembly-qualified name as string) and casting to IModule.

This approach requires you to know the exact class and assembly names of the modules (as you wrote, they could be stored in web.config).

Alternatively, you could go for a completely dynamic plugin approach:

  1. establish a convention that all module assemblies should be named "RIV.Module.XYZ"
  2. scan the bin directory for matching DLLs
  3. for each DLL, load it (eg Assembly.Load) and scan for types implementing IModule
  4. instantiate all found types and cast to IModule

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM