4

注意:所有示例代码都大大简化了。

我有一个 DLL 定义为:

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);
    }
}

现在,在我的解决方案之外,其他开发人员可以定义具体的类并将它们放入我的应用程序的 BIN 文件夹中。也许是这样的:

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)
        {
            //...
        }
    }
}

现在,在我的应用程序中,我需要知道有一个新模块可用(我猜测是通过 web.config 或类似的东西),然后能够根据数据库 Campaign 表中的某个触发器调用它(映射到用于该特定活动的模块)。

我正在尝试以这种方式实例化它:

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

但是,编译器会打嗝,因为从未将引用设置为RIV.Module.Greeting.dll

我究竟做错了什么?

4

2 回答 2

2

您需要使用更多反射:

  • 通过调用加载程序集Assembly.Load
  • 通过调用someAssembly.GetType(name)或搜索查找类型someAssembly.GetTypes()
  • Type将实例传递给Activator.CreateInstance
  • 将其投射到您的界面。
于 2011-02-09T00:42:57.727 回答
1

尝试使用 typeof(RIV.Module.Greeting.Module) 而不是 typeof(RIV.Module.Greeting.Module)

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

(即通过将其程序集限定名称指定为字符串来加载类型)并转换为 IModule。

这种方法要求您知道模块的确切类和程序集名称(如您所写,它们可以存储在 web.config 中)。

或者,您可以采用完全动态的插件方法:

  1. 建立一个约定,所有模块程序集都应命名为“RIV.Module.XYZ”
  2. 扫描 bin 目录以查找匹配的 DLL
  3. 对于每个 DLL,加载它(例如 Assembly.Load)并扫描实现 IModule 的类型
  4. 实例化所有找到的类型并转换为 IModule
于 2011-02-09T00:46:24.667 回答