2

我正在为 Asp.net MVC 2 开发一个插件系统。我有一个包含控制器和视图作为嵌入式资源的 dll。

我使用 StructureMap 扫描控制器的插件 dll,然后我可以将它们拉出并在请求时实例化它们。这工作正常。然后我有一个 VirtualPathProvider 改编自这篇文章

public class AssemblyResourceProvider : VirtualPathProvider
{
    protected virtual string WidgetDirectory
    {
        get 
        { 
            return "~/bin";
        }
    }

    private bool IsAppResourcePath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return checkPath.StartsWith(WidgetDirectory, StringComparison.InvariantCultureIgnoreCase);
    }

    public override bool FileExists(string virtualPath)
    {
        return (IsAppResourcePath(virtualPath) || base.FileExists(virtualPath));
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        return IsAppResourcePath(virtualPath) ? new AssemblyResourceVirtualFile(virtualPath) : base.GetFile(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies,
                                                       DateTime utcStart)
    {
        return IsAppResourcePath(virtualPath) ? null : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }
}

internal class AssemblyResourceVirtualFile : VirtualFile
{
    private readonly string path;

    public AssemblyResourceVirtualFile(string virtualPath)
        : base(virtualPath)
    {
        path = VirtualPathUtility.ToAppRelative(virtualPath);
    }

    public override Stream Open()
    {
        var parts = path.Split('/');
        var resourceName = Path.GetFileName(path);

        var apath = HttpContext.Current.Server.MapPath(Path.GetDirectoryName(path));
        var assembly = Assembly.LoadFile(apath);
        return assembly != null ? assembly.GetManifestResourceStream(assembly.GetManifestResourceNames().SingleOrDefault(s => string.Compare(s, resourceName, true) == 0)) : null;
    }
}

VPP 似乎也运行良好。找到视图并将其拉出到流中。然后我收到一个解析错误Could not load type 'System.Web.Mvc.ViewUserControl<dynamic>'.,我在前面的任何可插入视图示例中都找不到该错误。为什么我的观点在这个阶段不能编译?

谢谢你的帮助,

伊恩

编辑:

Getting closer to an answer but not quite clear why things aren't compiling. Based on the comments I checked the versions and everything is in V2, I believe dynamic was brought in at V2 so this is fine. I don't even have V3 installed so it can't be that. I have however got the view to render, if I remove the <dynamic> altogether.

So a VPP works but only if the view is not strongly typed or dynamic

This makes sense for the strongly typed scenario as the type is in the dynamically loaded dll so the viewengine will not be aware of it, even though the dll is in the bin. Is there a way to load types at app start? Considering having a go with MEF instead of my bespoke Structuremap solution. What do you think?

4

3 回答 3

2

The settings that allow parsing of strongly typed views are in ~/Views/Web.Config. When the view engine is using a virtual path provider, it is not in the views folder so doesn't load those settings.

If you copy everything in the pages node of Views/Web.Config to the root Web.Config, strongly typed views will be parsed correctly.

于 2011-01-01T09:41:54.140 回答
1

Try to add content of Views/Web.config directly to your main web.config under specific location, e.g. for handling virtual paths like ~/page/xxx. See more details here: http://blog.sergkazakov.com/2011/01/aspnet-strongly-typed-view-and-virtual.html

于 2011-01-17T11:40:49.513 回答
0

Is there a way to load types at app start?

Yes, you may use BuildManager.AddReferencedAssembly(assembly), where assembly is the one, containing the requested type. So, once you use MEF, the last should be easy, but beware, everything should be done before Application_Start, so you may wish to use PreApplicationStartMethodAttribute.

于 2015-09-07T16:49:13.730 回答