如何实例化未包含在 C# 项目中的对象?
注意:所有示例代码都已大大简化。
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要使用更多反射:
Assembly.Load
加载程序someAssembly.GetType(name)
或搜索someAssembly.GetTypes() 查找类型
Type
实例传递给Activator.CreateInstance
You need to use more reflection:
Assembly.Load
someAssembly.GetType(name)
or searchingsomeAssembly.GetTypes()
Type
instance toActivator.CreateInstance
而不是 typeof(RIV.Module.Greeting.Module)。
尝试使用(即通过将其程序集限定名称指定为字符串来加载类型)并转换为 IModule,
这种方法要求您知道模块的确切类和程序集名称(正如您所写,它们可以存储在 web.config 中)。
或者,您可以采用完全动态的插件方法:
Instead of typeof(RIV.Module.Greeting.Module), try using
(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: