繁体   English   中英

Assembly.CreateInstance():如何执行接口实现

[英]Assembly.CreateInstance(): how to enforce Interface implementation

我有一个要在运行时加载的dll。 我使用Assembly.Load(byte [])和.CreateInstance()加载的程序集。

在此程序集中,我有一个接口IAnimal和一个实现此接口的Cow:

namespace DynamicLoading
{    
    public class Cow : IAnimal
    {
        public string GetName()
        {
            return "This is cow";
        }
    }

    public interface IAnimal
    {
        string GetName();
    }
}

我使用控制台应用程序对此进行测试加载:

namespace DynamicLoading
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] assemblyStream = System.IO.File.ReadAllBytes(@"C:\Cow\Cow.dll");

            var cow = Assembly.Load(assemblyStream);

            //Returns null: it is not able to cast from Cow to IAnimal
            var newCow = cow.CreateInstance("DynamicLoading.Cow", false) as IAnimal;

            Console.WriteLine(newCow.GetName());                

            Console.ReadLine();
        }
    }

    public interface IAnimal
    {
        string GetName();
    }
}

我可以很好地实例化Cow的新实例,但是我似乎无法强制执行IAnimal接口(我在测试项目和dll项目中都创建了该接口)。 dll中的Cow不想从testclass转换为IAnimal。

如何在Cow上调用方法,例如GetName()?

大家好!

Cow.dll中的界面与其他程序集中的界面不同。 无论是在相同名称空间中使用相同名称的相同接口。

您需要做的是在“公共”位置定义接口,这对于Cow.dll和程序汇编都是可见的:

- Animals.Common.Dll
    - interface IAnimal

- Animals.Cow.Dll
    - References 
       - Animals.Common.Dll
    - class Cow: IAnimal

- Animals.Main.exe (Console Application)
    - References
       - Animals.Common.Dll
    - class Program

您有两个不同的接口,尽管它们具有相同的FullName ,但它们的AssemblyQualifiedName有所不同,因为它们属于两个不同的程序集。

在两个项目都引用的某些共享程序IAnimal使用IAnimal接口的单个​​定义。

如果您希望定期执行此类操作(类型的动态加载),请查看为创建加载项而设计的MAF

不要在多个位置定义接口,因为DynamicLoading库中实现的版本与类库中的版本不同。

在第三个程序集中创建它的一个版本,并从控制台和DynamicLoading程序集中引用该版本。

例如

程序集DynamicLoading.Core IAnimal

程序集DynamicLoading.Cow-参考DynamicLoading.Core

Consoe应用程序-参考DynamicLoading.Core

要注意的重要一点是每个接口都是不同的。 您已经定义了两个恰好具有相同形状的接口。 它们仍然是两个不同的接口。

有几种方法可以解决此问题,具体取决于应用程序的结构以及最终要实现的目标。

一种方法是让Cow程序集引用主程序集,并让Cow从那里实现IAnimal接口:

namespace Plugin
{
    public class Cow : MainAssembly.IAnimal { }
}

另一种方法是继续前进,并编写对对象使用反射的IAnimal代理实现

internal class AnimalProxy : IAnimal
{
    private object _target;
    public AnimalProxy(object target)
    {
        _target = target;
    }

    public string GetName()
    {
        //probably want to add error handling
        return _target.GetType().GetMethod("GetName").Invoke(_target) as string;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM