我正在使用Razor视图为ASP.NET MVC3设计一个插件框架,并且让嵌入式视图正常工作时出现问题.
>每个插件都有自己的模型,控制器和视图.视图是嵌入式资源,控件派生自PluginController类
>插件具有对定义PluginController基类的共享类库的依赖引用
>承载插件的“shell”Web应用程序在设计时不能保留对任何插件的引用,因为它在设计时不知道它具有哪些插件.
>插件dll被丢弃在shell应用程序的一个文件夹中,这不是/ bin文件夹
> shell负责:
发现插件(使用反射)
>注册所有控制器(我正在使用@L_301_1@.Net)
>创建到控制器的路由
>通过自定义的VirtualPathProvider为剃须刀文件(cshtml)服务
现在一切正常,除非嵌入视图引用了插件dll中的类型.然后我得到臭名昭着的错误(遗漏的名字):
命名空间'[MyPluginSolution]’中不存在类型或命名空间名称[插件])(您是否缺少程序集引用?)
这样做的原因是调用运行时编译剃刀视图的csc编译器只能从bin文件夹和GAC获取dll引用.
我也尝试使用this technique预编译视图,但最终给出了相同的结果,因为运行时坚持编译预编译的剃刀视图的包装器.
解决方法
好的,解决方案是使用
this article发现的.
首先我用PreApplicationStartMethod创建一个类.此方法扫描插件文件夹,并将dll复制到AppDomain.DynamicDirectory.
然后使用BuildManager.AddReferencedAssembly加载这些dll的每个.
而且,强大的剃刀视图编译精美.请看代码:
[assembly: PreApplicationStartMethod(typeof(MySolution.PluginHandler.PluginActivator),"Initialize")] namespace MySolution.PluginHandler { public class PluginActivator { private static readonly DirectoryInfo PluginFolderInfo; static PluginActivator() { PluginFolderInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/plugins")); } public static void Initialize() { CopyPluginDlls(PluginFolderInfo,AppDomain.CurrentDomain.DynamicDirectory); LoadPluginAssemblies(AppDomain.CurrentDomain.DynamicDirectory); } private static void CopyPluginDlls(DirectoryInfo sourceFolder,string destinationFolder) { foreach (var plug in sourceFolder.GetFiles("*.dll",SearchOption.AllDirectories)) { if (!File.Exists(Path.Combine(destinationFolder,plug.Name))) { File.Copy(plug.FullName,Path.Combine(destinationFolder,plug.Name),false); } } } private static void LoadPluginAssemblies(string dynamicDirectory) { foreach (var plug in Directory.GetFiles(dynamicDirectory,"*.dll",SearchOption.AllDirectories)) { Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(plug)); BuildManager.AddReferencedAssembly(assembly); } } } }
我希望这可以帮助其他想要使用这些新技术创建一个干净的插件框架的程序员.