首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ASP.NET MVC的插件体系结构

ASP.NET MVC的插件体系结构
EN

Stack Overflow用户
提问于 2008-12-04 10:40:22
回答 3查看 32K关注 0票数 70

我花了一些时间阅读Phil Haack在Grouping Controllers上的文章,非常有趣的东西。

目前,我正在尝试弄清楚是否有可能使用相同的想法来为我正在工作的项目创建插件/模块化架构。

所以我的问题是:有没有可能将Phil文章中的区域分割到多个项目中?

我可以看到名称空间将自动工作,但我担心视图最终会出现在正确的位置。它是可以通过构建规则进行排序的东西吗?

假设在单个解决方案中使用多个项目可以实现上述目标,那么有没有人知道如何通过单独的解决方案和对一组预定义的接口进行编码来实现这一目标的最佳方法?从一个区域移动到一个插件。

我有一些插件架构的经验,但不是大众的,所以在这方面的任何指导都会很有用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2008-12-04 17:07:09

几周前我做了一个概念验证,我把一个完整的组件堆栈:一个模型类,一个控制器类和它们的相关视图放到一个动态链接库中,添加/调整了检索视图的VirtualPathProvider类的one of the examples,这样它们就可以适当地处理动态链接库中的那些。

最后,我只需将DLL放入一个适当配置的MVC应用程序中,它就像从一开始就是MVC应用程序的一部分一样工作。我更进一步,它在5个迷你MVC插件上工作得很好。显然,你必须注意你的引用和配置依赖项,但它确实起作用了。

该练习旨在为我为客户端构建的基于MVC的平台提供插件功能。在站点的每个实例中,都有一组核心的控制器和视图,这些控制器和视图由更多可选的控制器和视图扩充。我们将把这些可选的部分放入这些模块化的DLL插件中。到目前一切尚好。

我在我的网站上写了一个我的原型的概述和一个sample solution for ASP.NET MVC plugins

编辑:4年过去了,我一直在做一些带有插件的ASP.NET MVC应用程序,不再使用我上面描述的方法。在这一点上,我所有的插件都是通过MEF运行的,根本没有把控制器放到插件中。相反,我制作了通用控制器,使用路由信息选择MEF插件,并将工作交给插件,等等。我只是想添加,因为这个答案得到了相当多的答案。

票数 52
EN

Stack Overflow用户

发布于 2008-12-09 16:38:20

因此,我对上面J Wynia中的示例做了一些修改。顺便说一句,非常感谢。

我进行了更改,以便VirtualPathProvider的扩展使用静态构造函数来创建系统中各种dll中以.aspx结尾的所有可用资源的列表。这很费力,但我们只做了一次。

这可能是对VirtualFiles的使用方式的完全滥用;-)

你最终会得到一个:

私有静态IDictionary resourceVirtualFile;

该字符串是虚拟路径。

下面的代码对.aspx文件的名称空间做了一些假设,但它在简单的情况下可以工作。这一点很好,因为您不必创建复杂的视图路径,它们是从资源名称创建的。

代码语言:javascript
复制
class ResourceVirtualFile : VirtualFile
{
    string path;
    string assemblyName;
    string resourceName;

    public ResourceVirtualFile(
        string virtualPath,
        string AssemblyName,
        string ResourceName)
        : base(virtualPath)
    {
        path = VirtualPathUtility.ToAppRelative(virtualPath);
        assemblyName = AssemblyName;
        resourceName = ResourceName;
    }

    public override Stream Open()
    {
        assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName + ".dll");

        Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyName);
        if (assembly != null)
        {
            Stream resourceStream = assembly.GetManifestResourceStream(resourceName);
            if (resourceStream == null)
                throw new ArgumentException("Cannot find resource: " + resourceName);
            return resourceStream;
        }
        throw new ArgumentException("Cannot find assembly: " + assemblyName);
    }

    //todo: Neaten this up
    private static string CreateVirtualPath(string AssemblyName, string ResourceName)
    {
        string path = ResourceName.Substring(AssemblyName.Length);
        path = path.Replace(".aspx", "").Replace(".", "/");
        return string.Format("~{0}.aspx", path);
    }

    public static IDictionary<string, VirtualFile> FindAllResources()
    {
        Dictionary<string, VirtualFile> files = new Dictionary<string, VirtualFile>();

        //list all of the bin files
        string[] assemblyFilePaths = Directory.GetFiles(HttpRuntime.BinDirectory, "*.dll");
        foreach (string assemblyFilePath in assemblyFilePaths)
        {
            string assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath);
            Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilePath);  

            //go through each one and get all of the resources that end in aspx
            string[] resourceNames = assembly.GetManifestResourceNames();

            foreach (string resourceName in resourceNames)
            {
                if (resourceName.EndsWith(".aspx"))
                {
                    string virtualPath = CreateVirtualPath(assemblyName, resourceName);
                    files.Add(virtualPath, new ResourceVirtualFile(virtualPath, assemblyName, resourceName));
                }
            }
        }

        return files;
    }
}

然后,您可以在扩展VirtualPathProvider中执行类似以下操作:

代码语言:javascript
复制
    private bool IsExtended(string virtualPath)
    {
        String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return resourceVirtualFile.ContainsKey(checkPath);
    }

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

    public override VirtualFile GetFile(string virtualPath)
    {
        string withTilda = string.Format("~{0}", virtualPath);

        if (resourceVirtualFile.ContainsKey(withTilda))
            return resourceVirtualFile[withTilda];

        return base.GetFile(virtualPath);
    }
票数 4
EN

Stack Overflow用户

发布于 2008-12-04 11:48:35

我想可以将视图留在插件项目中。

这就是我的想法:您需要一个调用插件(可能是通过接口)并请求视图(IView)的ViewEngine。然后,插件将不通过它的url (就像普通的ViewEngine那样- /Views/Shared/View.asp)而是通过它的视图名称(例如,通过反射或DI/IoC容器)来实例化视图。

插件中视图的返回甚至可能是硬编码的(下面是一个简单的例子):

代码语言:javascript
复制
public IView GetView(string viewName)
{
    switch (viewName)
    {
        case "Namespace.View1":
            return new View1();
        case "Namespace.View2":
            return new View2();
        ...
    }
}

...this只是一个想法,但我希望它能起作用,或者只是一个很好的灵感。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/340183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档