MVC3 Plugin System
I'm working on a plugin system that works with MVC3, DLL's are placed in the ~/Plugin/ directory. So far everything is working fine and dandy as models and controllers are found by the host and the views are properly embedded into the DLL's. The only problem is that views cannot be compiled by the Razor engine.
Models and controllers are added during the initialization phase of the application like this:
[assembly: PreApplicationStartMethod(typeof(Dashboard.PluginReader), "Initialize")]
namespace Dashboard
{
public class PluginReader
{
public static void Initialize()
{
foreach (string plugin in Directory.GetFiles(HostingEnvironment.MapPath("~/Plugin"), "*.dll", SearchOption.AllDirectories))
{
Assembly assembly = Assembly.LoadFile(plugin);
BuildManager.AddReferencedAssembly(assembly);
}
}
}
}
In order to resolve the views I use a VirtualFile and a VirtualPathProvider which return the requested resour开发者_开发问答ce as stream like this:
class AssemblyResourceVirtualFile : VirtualFile
{
string path;
public AssemblyResourceVirtualFile(string virtualPath)
: base(virtualPath)
{
path = VirtualPathUtility.ToAppRelative(virtualPath);
}
public override System.IO.Stream Open()
{
// /~Plugin/path.of.dll/path.of.razor.view
string[] parts = path.Split('/');
string assemblyName = parts[2];
string resourceName = parts[3];
string path = HostingEnvironment.MapPath("~/Plugin") + "/"+ assemblyName;
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(path);
if (assembly != null)
{
Stream resourceStream = assembly.GetManifestResourceStream(resourceName);
return resourceStream;
}
return null;
}
}
As Razor compiles them it returns an exception as it cannot find the references such as ViewBag. Does anyone have an idea on how to make these embedded resources work or know an existing plugin system?
The following post looks very useful for this http://www.chrisvandesteeg.nl/2010/11/22/embedding-pre-compiled-razor-views-in-your-dll/
Answer
If you want to make a plugin like this you just do the following:
- Follow the instructions on the site of Chris van de Steeg http://www.chrisvandesteeg.nl/2010/11/22/embedding-pre-compiled-razor-views-in-your-dll/
- Copy the controllers to the class library as well
- Copy the PluginActivator class A plugin framework with ASP.NET MVC3 and embedded Razor views. The DLL needs to be in the bin or GAC to work.
And finally, place this in the Application_Start().
protected void Application_Start()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
// As you can see, it checks if the assembly has plugin in it's name
// If you want something more solid, replace it at will
if (assembly.ManifestModule.Name.ToLower().Contains("plugin"))
{
BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register(assembly);
}
}
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
精彩评论