是否可以使用C#进行早期绑定接口和后期绑定实现

时间:2015-02-04 00:52:04

标签: c# reflection interface

我试图创建一个本质上是项目的插件框架。我试图在完全开发之前解决这些问题并且我遇到了问题。我正在构建一个消息处理器。消息的来源决定了消息的处理方式。无论消息来自哪里,检索消息和发送消息都是一样的,我觉得插件框架是实现这个的好方法。

我构建了一个可以构建所有实现的接口。

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调用方法来实现这一点,但我希望保持代码比这更清晰,因为我们的开发组中的其他人需要支持这一点,并且当涉及到更简单时更简单其中一些。

谢谢!

2 个答案:

答案 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;

纠正了这个问题。我不确定为什么它将这些视为两种不同的类型,但确实如此。

谢谢彼得。