У меня возникла проблема с литьем объекта на один из его базовых интерфейсов, живущих в другой библиотеке. Вот код для этого:литье объекта в базовый интерфейс
BaseSDK.dll
public interface IPlugin
{
void Run();
}
CustomPlugin.Definition.dll:
public interface ICustomPlugin
{
void DoCustomStuff();
}
CustomPlugin.dll (имеет отношение к BaseSDK.dll и CustomPlugin.Definition.dll):
public class CustomPlugin: IPlugin, ICustomPlugin
{
public void Run()
{
}
public void DoCustomStuff()
{
}
}
host.exe (имеет ссылки на BaseSDK.dll и CustomPlugin.Definition.dll):
IPlugin plugin;
public void DoStuff()
{
plugin = LoadPluginAndCreateAnInstanceSomehow();
// I know plugin is a CustomPlugin
ICustomPlugin customPlugin = plugin as ICustomPlugin; //cast fails.
customPlugin.DoCustomStuff();
}
Я не понимаю; это простой тип, накладывающий тип на его базовый тип. Как я могу это исправить? или какие-либо альтернативы?
Edit: Вот краткое изложение того, что LoadPluginAndCreateAnInstanceSomehow()
делает:
Assembly ass = Assembly.LoadFrom(filename);
Type t = ass.GetType(ass.FullName + ".CustomPlugin");
plugin = (IPlugin)Activator.CreateInstance(t);
Edit 2: Плагины загружаются в другой AppDomain. Я должен был добавить IPlugin и ICustomPlugin.Definiton в качестве ссылки во время компиляции, потому что приложение должно иметь представление о том, что такое CustomPlugin. это источник проблемы? если да, то как я могу достичь того, что я пытаюсь сделать?
Edit 3: Плагины загружаются так:
public class PluginLoader
{
List<IPlugin> Plugins;
AppDomain Domain;
string libPath;
public void PluginLoader(string sLibPath, AppDomain sDomain)
{
libPath = sLibPath;
Plugins = new List<IPlugin>();
Domain = sDomain;
if(Domain==null)Domain = AppDomain.CreateDomain("PluginsDomain");
Domain.AssemblyResolve += new ResolveEventHandler(Domain_AssemblyResolve);
Domain.TypeResolve += new ResolveEventHandler(Domain_TypeResolve);
Domain.DoCallBack(new CrossAppDomainDelegate(DomainCallback));
}
Assembly Domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return Assembly.LoadFrom(args.Name);
}
Assembly Domain_TypeResolve(object sender, ResolveEventArgs args)
{
return Assembly.LoadFrom(args.Name);
}
void DomainCallback()
{
string[] fileNames = Directory.GetFiles(libPath, "*.dll");
foreach (string filename in fileNames)
{
FileInfo fi = new FileInfo(filename);
Assembly ass = Assembly.LoadFrom(fi.FullName);
Type t = ass.GetType(ass.FullName + ".CustomPlugin");
IPlugin p = (IPlugin)Activator.CreateInstance(t);
Plugins.Add(p);
}
}
}
Можете ли вы показать нам, как вы загружаете плагин в другой AppDomain? Я пробовал это с dll в разных местах, но я не могу повторить вашу проблему. – Sam
Assembly ass = Assembly.LoadFrom (fi.FullName). lol при имени переменной. – obelix
Я в замешательстве. Почему существует ожидание того, что типы, загруженные из другого домена приложения, будут совместимы с теми же типами, которые загружаются в текущий домен приложения? –