我试图创建一个本质上是项目的插件框架。我试图在完全开发之前解决这些问题并且我遇到了问题。我正在构建一个消息处理器。消息的来源决定了消息的处理方式。无论消息来自哪里,检索消息和发送消息都是一样的,我觉得插件框架是实现这个的好方法。
我构建了一个可以构建所有实现的接口。
IIPInterfaces.cs:
using System;
using System.Xml;
namespace IIPInterfaces
{
public interface IInterfaceProcessor
{
IIPResult ProcessRequest(XmlDocument xdoc, String processType);
}
public class IIPResult
{
public XmlDocument ResponseDocument { get; set;}
Boolean IsSuccessful { get; set; }
String Error { get; set; }
}
}
我为界面创建了一个实现,只是为了测试它。
PrototypeIIP
using IIPInterfaces;
using System;
using System.Xml;
namespace PrototypeIIP
{
public class IIPImplimentation : IInterfaceProcessor
{
public IIPResult ProcessRequest(XmlDocument xdoc, String requestType)
{
IIPResult result = new IIPResult();
Console.WriteLine("In interface {0}", requestType);
return result;
}
}
}
然后我创建了一个测试项目,尝试在运行时绑定实现文件,然后使用该接口。
控制台计划
using IIPInterfaces;
using System;
using System.IO;
using System.Reflection;
using System.Xml;
namespace LateBindingPrototype
{
class Program
{
static void Main(string[] args)
{
String filePath = "C:\\XMLConfig\\PrototypeIIP.dll";
// Try to load a copy of PrototypeIIP
Assembly a = null;
try
{ a = Assembly.LoadFrom(filePath); }
catch(FileNotFoundException e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
return;
}
if (a != null)
{ CreateUsingLateBinding(a); }
Console.ReadKey();
InvokeProcessMessage(a);
Console.ReadKey();
}
static void InvokeProcessMessage(Assembly asm)
{
try
{
Type processor = asm.GetType("PrototypeIIP.IIPImplimentation");
IInterfaceProcessor myProcessor = Activator.CreateInstance(processor) as IInterfaceProcessor;
XmlDocument xdoc = new XmlDocument();
myProcessor.ProcessRequest(xdoc, "test");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
}
}
static void CreateUsingLateBinding(Assembly asm)
{
try
{
Type processor = asm.GetType("PrototypeIIP.IIPImplimentation");
object obj = Activator.CreateInstance(processor);
Console.WriteLine("Created a {0} using late finding!", obj);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
}
}
}
}
CreateUsingLateBinding方法工作正常,但是当我尝试在InvokeProcessMessage方法中的IInterfaceProcessor实例中创建时,该对象为null。
我想做的是什么?我知道我可以通过绕过接口并直接从实现dll调用方法来实现这一点,但我希望保持代码比这更清晰,因为我们的开发组中的其他人需要支持这一点,并且当涉及到更简单时更简单其中一些。
谢谢!
答案 0 :(得分:2)
您描述的问题最明显的解释是,在声明实现接口的类型时,您在DLL中使用的接口类型IInterfaceProcessor
不是相同的接口类型(也称为IInterfaceProcessor
)您在尝试创建实例时在程序中使用。
即。 Activator.CreateInstance()
实际上返回一个非空引用(除非引发异常,否则它将一直返回),但该类型不会实现您尝试使用as
运算符将其强制转换为的接口。
我发现这种情况的最常见原因是在某些.cs文件中声明了一个类型,而不是将.cs文件编译成单个DLL并通过该DLL引用该类型,该文件是链接到两个或多个项目,分别编译到每个项目中。这会产生一个新类型,每个组件一个,当然类型也不兼容。
当然,缺少a good, complete code example我无法确定这实际上是您代码中的问题。这只是一个有根据的猜测。
所有这一切,对于你似乎想要做的事情类型,最好使用Managed Extensibility Framework。它提供了一个有用的API,可用于构建这种功能。
除此之外,我认为程序中的硬编码类型名称仅用于测试目的。当然,对于真正的插件架构,您只需要枚举程序集中的所有类型,寻找那些实现您感兴趣的接口的类型。
答案 1 :(得分:0)
在彼得的回应之后,我回去试图更具体一点。
在PrototypeIIP.cs
中public class IIPImplimentation : IInterfaceProcessor
到
public class IIPImplimentation : IIPInterfaces.IInterfaceProcessor
在控制台程序中
IInterfaceProcessor myProcessor = Activator.CreateInstance(processor) as IInterfaceProcessor;
到
IIPInterfaces.IInterfaceProcessor myProcessor = Activator.CreateInstance(processor) as IIPInterfaces.IInterfaceProcessor;
纠正了这个问题。我不确定为什么它将这些视为两种不同的类型,但确实如此。
谢谢彼得。