与ASP.NET MVC3和一个插件架构的嵌入式刀片意见 [英] A plugin framework with ASP.NET MVC3 and embedded Razor views

查看:158
本文介绍了与ASP.NET MVC3和一个插件架构的嵌入式刀片意见的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用剃刀的意见设计的插件框架ASP.NET MVC3,和我有一个问题让嵌入式意见才能正常工作。

插件框架被设计成具有以下功能:


  • 每个插件都有自己的模型,控制器和视图。该意见的嵌入式资源的,且控制器的从PluginController类派生

  • 的插件有一个共享的类库,它定义了PluginController基类的依赖引用

  • 托管插件的壳Web应用程序的一定不能保留在设计时任何插件引用,因为它不知道它有哪些插件设计时间。

  • 插件DLL的是一个文件夹在外壳应用程序,这是下跌的不是/ bin文件夹

  • 外壳需要照顾:

    1. 发现插件(使用反射)

    2. 注册的所有控制器(我用Spring.Net本)

    3. 创建路由到控制器

    4. 通过定制服务剃刀文件(CSHTML)的VirtualPathProvider


现在一切正常,除了当嵌入式意见有插件DLL内类型的引用。然后我得到了臭名昭著的错误(名字省略):

类型或命名空间名称'[插件]'不会在命名空间[MyPluginSolution]'存在(是否缺少程序集引用?)

这样做的原因是,CSC编译器被调用运行时编译剃刀意见的只能从bin文件夹和GAC的DLL引用

我也试过$ P $使用的这种技术但最终它给出了相同的结果,因为运行时编译上一个包装为pre-编译的Razor视图坚持。

我当然可以滴在/ bin文件夹中的插件DLL,但我的问题是:

有没有在非斌(和非GAC)文件夹中注册DLL文件,并将它们视为使他们能够通过剃刀视图中使用的一等公民的方式?


解决方案

好了,该解决方案采用的这篇文章

首先,我创建一个类以 preApplicationStartMethod 。这种方法扫描插件文件夹并拷贝dll文件到 AppDomain.DynamicDirectory

然后每个DLL的使用加载的 BuildManager.AddReferencedAssembly

,瞧,强类型的刀片意见编译粉墨登场。看到这里的code:

[汇编:preApplicationStartMethod(typeof运算(MySolution.PluginHandler.PluginActivator),初始化)]
命名空间MySolution.PluginHandler
{
    公共类PluginActivator
    {
        私人静态只读的DirectoryInfo PluginFolderInfo;        静态PluginActivator(){
            PluginFolderInfo =新的DirectoryInfo(HostingEnvironment.MapPath(〜/插件));
        }        公共静态无效初始化(){
            CopyPluginDlls(PluginFolderInfo,AppDomain.CurrentDomain.DynamicDirectory);
            LoadPluginAssemblies(AppDomain.CurrentDomain.DynamicDirectory);
        }        私有静态无效CopyPluginDlls(DirectoryInfo的sourceFolder,串destinationFolder)
        {
            的foreach(VAR插上sourceFolder.GetFiles(*。DLL,SearchOption.AllDirectories)){
                如果(!File.Exists(Path.Combine(destinationFolder,plug.Name))){
                    File.Copy(plug.FullName,Path.Combine(destinationFolder,plug.Name),FALSE);
                }
            }
        }        私有静态无效LoadPluginAssemblies(字符串dynamicDirectory)
        {
            的foreach(VAR插件Directory.GetFiles(dynamicDirectory,* .DLL,SearchOption.AllDirectories)){
                装配装配=的Assembly.Load(AssemblyName.GetAssemblyName(插头));
                BuildManager.AddReferencedAssembly(组装);
            }
        }
    }
}

我希望这可以帮助那些希望利用这些新技术来创造一个干净的插件框架其他程序员。

I'm designing a plugin framework for ASP.NET MVC3 using Razor views, and I'm having an issue getting the embedded views to work correctly.

The plugin framework is designed to have these features:

  • Each plugin has its own models, controllers and views. The views are embedded resources, and the controllers derive from a PluginController class
  • The plugins have dependency references to a shared class library that defines the PluginController base class
  • The "shell" web application that hosts the plugins must not hold references to any plugins at design time, since it does not know at design time which plugins it has.
  • The plugin dll's are dropped in a folder in the shell application, which is not the /bin folder
  • The shell takes care of:

    1. Discovering the plugins (using reflection)
    2. Registering all controllers (I'm using Spring.Net for this)
    3. Creating routes to the controllers
    4. Serving the razor files (cshtml) through a custom VirtualPathProvider

Now everything works fine, except when the embedded views have references to types within the plugin dll. Then I get the infamous error (names left out):

The type or namespace name '[Plugins]' does not exist in the namespace '[MyPluginSolution]' (are you missing an assembly reference?)

The reason for this is that the csc compiler which is invoked runtime to compile the razor views only get the dll references from the bin folder and the GAC.

I've also tried pre-compiling the views using this technique but in the end it gives the same results, since the runtime insists on compiling a wrapper for the pre-compiled razor view.

I could of course drop the plugin dll in the /bin folder, but my question is:

Is there a way to register dlls in a non-bin (and non-GAC) folder, and treat them as "first class citizens" so they can be used by the razor views?

解决方案

Ok, the solution was found using this article.

First I create a class with a PreApplicationStartMethod. This method scans the plugin folder and copies the dlls to the AppDomain.DynamicDirectory.

Then each of these dll's are loaded using BuildManager.AddReferencedAssembly.

And voilà, the strongly-typed Razor views compile beautifully. See the code here:

[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);
            }
        }
    }
}

I hope this can help other programmers that want to create a clean plugin framework using these new technologies.

这篇关于与ASP.NET MVC3和一个插件架构的嵌入式刀片意见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆