如何实例化未包含在 C# 项目中的对象?

发布于 2024-10-16 09:29:15 字数 1527 浏览 9 评论 0原文

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

我有一个 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 或类似的东西),然后能够根据数据库活动中的某些触发器来调用它表(映射到用于该特定活动的模块)。

我试图以这种方式实例化它:

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

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

我做错了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仅一夜美梦 2024-10-23 09:29:15

您需要使用更多反射:

  • 通过调用 Assembly.Load 加载程序
  • 集 通过调用 someAssembly.GetType(name) 或搜索 someAssembly.GetTypes() 查找类型
  • Type 实例传递给 Activator.CreateInstance
  • 将其投射到您的界面。

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.
哎呦我呸! 2024-10-23 09:29:15

而不是 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 目录以查找
  3. 每个 DLL 的匹配 DLL,加载它(例如 Assembly.Load)并扫描对于实现 IModule 的类型,
  4. 实例化所有找到的类型并转换为 IModule

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 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 (e.g. Assembly.Load) and scan for types implementing IModule
  4. instantiate all found types and cast to IModule
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文