如何在运行时引用mvc中的程序集

时间:2015-06-28 06:43:07

标签: c# asp.net-mvc razor mef

在我的Asp.Net MVC应用程序中,我有一些视图文件(.cshtml),它引用了一个外部库,它将在运行时加载。所以在应用程序启动之后,我通过Assembly.Load加载程序集,并通过我自己的自定义ControllerFactory注册控制器,并且每件事都没问题。

但是,在一些引用动态加载程序集的视图中,抛出:

  

编译器错误消息:CS0234:命名空间“MyApp”中不存在类型或命名空间名称“MyDynamicNamespace”(您是否缺少程序集引用?)

异常,告诉剃刀编译器无法解析相关的程序集。

我的问题是,有没有办法在运行时注册程序集,剃刀编译器是否可以访问它并解决它?

注意我无法使用BuildManager.AddReferencedAssembly方法,因为我的程序集必须在应用启动后加载,而BuildManager不支持它。

3 个答案:

答案 0 :(得分:9)

1)我不建议您的视图直接使用外部引用或动态加载的外部引用。通过让您的视图与控制器交互来抽象这一点。使控制器将一个数据对象提供给您的应用程序在构建时已知的视图(换句话说,就是构建时Web应用程序已知的对象)。这是为了从您的视图中完全隔离(抽象)插件特定的业务。然后让你的控制器与"插件"。

进行交互

2)我不知道你的定制工厂"虽然有效,但现在我们并没有真正建立任何定制工厂"了。相反,我们利用依赖注入容器,如Microsoft Unity(或Ninject,或Castle Windsor等)。创建"定制工厂"是非常老式的,你基本上重新发明了通过依赖注入解决的轮子。

3)至于动态加载外部程序集,我不知道你是否正确但是这里有一个链接:

Dynamically load a type from an external assembly

4)通常,插件设计会在构建时公开主Web应用程序已知的接口。插件设计隐藏的是可以从一个插件更改为另一个插件的实现。重要的是每个插件都实现了相同的公共接口,即主Web应用程序所需的接口。通常,您将在单独的" Common"由您的主Web应用程序和实现这些接口的插件引用的项目。因此,从您的主Web应用程序中,您将了解插件的公共接口是什么,您可以动态加载外部程序集并使用C#反射来查找实现这些接口的类并将它们加载到依赖项注入容器中。同样,任何想要为您的Web应用程序开发插件的人都必须实现在" Common"中定义的接口。项目。

注意:"普通"只是我给项目的随机名称。你可以命名它" PluginInterface"或者你想要的任何东西。

之后,让你的控制器从依赖注入容器中获取所需的任何内容都是微不足道的。

注意:您的插件接口可能包含输入和输出实体。这些实体在您的主Web应用程序和插件之间共享。在这种情况下,由于这些实体是您的接口的一部分,因此它们需要位于" Common"项目。您可能想让控制器将这些实体直接返回到您的视图,但是您不会在视图和插件之间获得完美的抽象。没有完美的抽象是另一个讨论。

希望它有所帮助!

答案 1 :(得分:6)

作为系统管理员,我会建议维护期,特别是如果您替换的文件混淆了其他内容。即使您的维护期仅为半小时,也是不错的做法。

对于DLL和重新编译...通常,IIS工作进程(运行应用程序池的服务)将根据IIS配置和内存使用情况以正常间隔进行回收。发生这种情况时,如果有任何需要JIT,应用程序将重新编译。它还会终止所有打开的用户会话,因为它会物理停止然后重新启动。对于任何文件更改,工作进程还会监视根目录(如您所述)。如果发现任何,则强制重新编译。仅仅因为依赖项被更改不会强制重新编译。如果你预先编译你的DLL,那么编译的唯一内容就是实际ASPX文件中的任何代码,并且它使用每次编译的JIT。根据您的描述,IIS不需要重新编译或重新启动,听起来像是在交换文件时IIS挂起的另一个问题。可能需要让sys管理员参与查看IIS日志。

祝你好运!

http://msdn.microsoft.com/en-us/library/ms366723.aspx

http://msdn.microsoft.com/en-us/library/bb398860.aspx

答案 2 :(得分:2)

以下是一条可能有用的注释:如果您没有从/bin目录加载程序集,则需要确保程序集的路径是可发现的:

AppDomain.CurrentDomain.AppendPrivatePath(path_to_your-dyna_assembly);