我有一个我想在运行时加载的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的牛不希望从测试类中转移到IAnimal。
如何在Cow上调用方法,例如GetName()?
干杯!
答案 0 :(得分:3)
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
答案 1 :(得分:2)
你有两个不同的界面,即使它们具有相同的FullName
,它们的AssemblyQualifiedName
也不同,因为它们属于两个不同的集合。
在两个项目引用的某个共享程序集中使用IAnimal
接口的单个定义。
如果您希望定期执行此类操作(动态加载类型),请查看专为创建插件而设计的MAF。
答案 2 :(得分:1)
不要在多个位置定义界面,DynamicLoading库中实现的版本与类库中的版本不同。
在第3个程序集中创建它的一个版本,并从控制台和DynamicLoading程序集引用它。
E.g。
程序集DynamicLoading.Core IAnimal
程序集DynamicLoading.Cow - 参考DynamicLoading.Core
Consoe Application - 参考DynamicLoading.Core
答案 3 :(得分:1)
需要注意的重要一点是每个界面都是截然不同的。您已经定义了两个仅碰巧具有相同形状的接口。它们仍然是两个不同的接口。
有几种方法可以解决这个问题,具体取决于应用程序的结构以及您最终要完成的任务。
一种方法是让你的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;
}
}