3

我放入了一个包含 MVC 控制器的程序集,我想将其用作 MvcPlayer 函数的目标。

当我尝试渲染页面时,虽然函数输出表明找不到我的控制器。

是否有一种特殊的技术可以让 Composite 注册我添加到 bin 目录的程序集中可用的控制器?

4

1 回答 1

3

所以我对能够使用 StructureMap 来解决这个问题的怀疑是有根据的。

StructureMap 是 .NET 的 DI/IoC 工具。不过,您可以使用任何其他 DI/IoC 工具(包括您自己的手动启动工具)以类似的方式解决此问题。

如果您没有使用 StructureMap 的经验,我建议您阅读一些有关它的文档。这是一个很好的视频教程,您可以使用:

以下文章介绍了 StructureMap 并讨论了我用于解决问题的自定义控制器工厂解决方案:

如果您对自定义控制器工厂不太了解,我会阅读以下文章。本文还为您提供了一些很好的线索,让您了解如何进行自己的手动 IoC(而不是使用 StructureMap 等)。

一句警告!在引用具有对先前版本 MVC3 的显式引用的库时,您可能会遇到问题。据我所知,Composite C1 v4.0 beta2 和 MvcPlayer 函数依赖于 MVC4 及其相关库。为了防止版本冲突,将以下部分添加到您的 web.config 以确保引用始终针对正确的版本:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Helpers" 
           publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Mvc" 
           publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.WebPages" 
           publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
    </dependentAssembly>
   </assemblyBinding>
</runtime>

好的,现在您已经掌握了速度,下面是采用 StructureMap 方法所需的所有代码。

我有一个 StructureMap 控制器约定:

public class ControllerConvention : ITypeScanner
{
    public void Process(Type type, PluginGraph graph)
    {
        if (typeof(IController).IsAssignableFrom(type) && !type.IsAbstract && !type.IsGenericType)
        {
            graph.AddType(typeof(IController), type, type.Name.Replace("Controller", "").ToLower());
        }
    }
}

控制器约定告诉 StructureMap 如何找到我的 MVC 控制器类,这很容易做到,因为我只需要查找实现 IController 接口的类。

对于您的 StructureMap 初始化,通常在应用程序启动时完成(有关示例,请参见结构图文档),您可以通过程序集扫描控制器以及控制器约定:

var controllerAssemblies = new List<Assembly>()
    {
        typeof(YourController).Assembly,
        typeof(AnotherController).Assembly
    };

ObjectFactory.Initialize(initialization =>
{
    initialization.Scan(scan =>
    {
        foreach (var assembly in controllerAssemblies)
        {
            scan.Assembly(assembly);
        }

        scan.With<ControllerConvention>();
    });
});

现在我们需要一个自定义控制器工厂:

public class StructureMapControllerFactory : DefaultControllerFactory 
{ 
    protected override IController GetControllerInstance(Type controllerType) 
    {
        try 
        {
            return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (StructureMapException) 
        {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

最后,我们需要在 App_Code/Composite/AspNet/MvcPlayer/Route.cs 类中注册我们自定义控制器工厂的使用:

ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
于 2013-03-18T11:13:14.673 回答