Некоторое время назад я делал нечто подобное в отношении системы типа плагинов, где плагины, где страницы и элементы управления, но хранились в отдельных сборках.
То, что мы в конечном итоге сделали, было:
Зарегистрируйте пользовательский VirtualPathProvider в Application_Start:
void Application_Start(object sender, EventArgs e)
{
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(
new YourCustomVirtualPathProvider());
}
Переопределите необходимые методы в VirtualPathProvider (в зависимости от вашей логики):
public class YourCustomVirtualPathProvider : System.Web.Hosting.VirtualPathProvider
{
private const string RESERVED_PATH = "/components/external";
public override bool FileExists(string virtualPath)
{
if (virtualPath.StartsWith(RESERVED_PATH))
return true;
else
return base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (virtualPath.StartsWith(RESERVED_PATH))
return new MyCustomVirtualFile(virtualPath);
else
return base.GetFile(virtualPath);
}
//You'll also need to override methods for directories, omitted for brevity.
}
Теперь создайте класс MyCustomVirtualFile
для загрузки файлов из сборки:
public class MyCustomVirtualFile : System.Web.Hosting.VirtualFile
{
private string _virtualPath;
public MyCustomVirtualFile(string virtualPath) { _virtualPath = virtualPath }
public override System.IO.Stream Open()
{
//You'll need some method to tie a virtual path to an assembly
//Then load the file from the assembly and return as a Stream
Assembly assembly = Foo.GetAssemblyByVirtualPath(_virtualPath);
string fileName = Foo.GetFileNameFromVirtualPath(_virtualPath);
return assembly.GetManifestresourceStream(fileName);
}
}
ASPX / ASCX или файлы ресурсов, которые вы хотите загрузить таким образом, должны быть добавлены в сборку как встроенный ресурс. Вы можете сделать это, изменив свойство «Build Action» файла:
Кодовый код будет скомпилирован в сборку, и если вы используете общую папку bin
, вам не нужно больше ничего делать. Если они не будут переданы, вам нужно будет присоединиться к событиям AssemblyResolve
и TypeResolve
в глобальном приложении (подробнее об этом здесь ).
В конечном итоге мы отказались от этой идеи из-за проблем безопасности и в итоге заключили MEF контракты на данные, но если все остальные ваши сборки являются первыми, то это должно быть быстро и легко. Надеюсь, это поможет.