Unity:无法从不同的程序集注册类型

7

我正在尝试在我的MVC应用程序中实现依赖注入。我正在使用Unity.Mvc3.dll进行IoC。我想知道为什么Unity无法从另一个程序集注册类型。以下是代码:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    var container = new UnityContainer();

    // ok: register type from this assembly
    container.RegisterType<IMessages, Messages>();

    // fail: register type from another assembly (service reference)
    container.RegisterType<IPlayerService, PlayerService>();

    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

public class UnityDependencyResolver : IDependencyResolver
{
    private readonly IUnityContainer _container;

    public UnityDependencyResolver(IUnityContainer container)
    {
        this._container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

MVC控制器中的使用:

[Dependency]
public IPlayerService PlayerService { get; set; }

[Dependency]
public IMessages Messages { get; set; }


public ActionResult Index()
{
    PlayerMessageViewModel vm = new PlayerMessageViewModel();
    vm.Messages = Messages; // success!
    vm.Players = PlayerService.Get(); // fail: null reference exception :PlayerService

    return View(vm);
}

PlayerService 在消息正常的情况下始终为空。

这是 PlayerService 类:

public class PlayerService : IPlayerService
{
    private readonly MyDbEntities _dbContext;

    public PlayerService()
    {
        _dbContext = new MyDbEntities();
    }

    public PlayerService(MyDbEntities dbContext)
    {
        _dbContext = dbContext;
    }


    public IQueryable<Player> Get()
    {
        return _dbContext.Players.AsQueryable();
    }
}

这是完整的错误信息

依赖项解析失败,类型 = "System.Web.Mvc.IControllerFactory",名称 = "(none)"。
异常发生在:解析期间。
异常信息:InvalidOperationException - 当前类型 System.Web.Mvc.IControllerFactory 是一个接口,无法构造。您是否缺少类型映射?

4个回答

7
您正在使用catch { return null; }隐藏所有异常,请尝试删除它并查看在解析过程中抛出的异常。我认为异常是在PlayerService构造函数中抛出的。
编辑:
来源:http://mvchosting.asphostcentral.com/post/ASPNET-MVC-3-Hosting-Problem-in-implementing-IControllerActivator-in-ASPNET-MVC-3.aspx 当MVC应用程序首次启动时,依赖项解析器按以下顺序调用以下类型:
- IControllerFactory - IControllerActivator - HomeController 如果您没有实现解析器以返回null(如果未注册类型),则可能会看到类似以下错误:
当前类型System.Web.Mvc.IControllerFactory是一个接口,无法构造

它应该调用默认构造函数,对吧?我无法让调试器进入构造函数中的断点。 - lincx
是的,public PlayerService() - Pavel Krymets
我移除了空值并替换为抛出异常,然后得到了以下结果:当前类型 System.Web.Mvc.IControllerFactory 是一个接口,不能构造它。你是否缺少类型映射? - lincx
玩家服务有问题吗?我认为问题不在 MyDbEntities,它是一个 Entity Framework edmx。 - lincx
我也找到了那个链接,但是真的不太理解,我需要实现IControllerFactory吗?它应该放在我的代码哪里呢?我对MVC还是个新手,更别提Unity了。唉,头疼啊。 - lincx
显示剩余2条评论

7

默认情况下,Unity会选择参数最多的构造函数,因此我认为它将尝试使用带有dbContext参数的第二个构造函数,但无法解析。如果您使用属性[InjectionConstructor]标记默认构造函数,则希望能解决您的问题。


包含哪个库的InjectionConstructor属性? - lincx
http://msdn.microsoft.com/en-us/library/microsoft.practices.unity.injectionconstructorattribute(v=pandp.20).aspx - Fergus Bown
仍然没有运气,我甚至删除了重载的构造函数,但是没有用。 - lincx
我认为这个问题没有解决办法,其他人怎么使用WCF服务类型实现了呢? - lincx
嗯,那我不确定了,我猜你得实施其他人提出的建议,尝试让无法解析的类型产生更有意义的消息。 - Fergus Bown
明白了,实际上出错的是构造函数,MyDbEntities(EF)在配置中有错误,我只是因为它没有抛出与EF相关的错误而感到困惑。我将把这标记为InjectionConstructor属性的答案,它实际上解决了具有两个构造函数的问题。非常感谢! - lincx

2
您正在违反IDependencyResolver的契约。对于无法解析的类型,它应返回null。 Unity的问题在于它尝试构建所有可以找到的类,无论它们是否在容器中注册。
因此,某个地方的类可能无法构建。
nuget中还有一个可用的Unity.Mvc3包。

1
你的 throw 隐藏了最初出现的问题,因为 IControllerActivator 在任何控制器被调用之前就已经被调用了。把它改回返回 null 并记录所有异常(或在 catch 块中设置断点)。 - jgauffin
已将其还原,并在catch中设置了断点:这是内部异常:当前类型System.Web.Mvc.IControllerFactory是一个接口,无法构造。您是否缺少类型映射? - lincx
1
继续返回null,直到控制器被调用,对于所有ASP.NET/MVC3类都是如此。我们感兴趣的是那个异常。 - jgauffin
谢谢,伙计。通过不断尝试和错误的钻研,我明白了。实际上应该返回 null,PlayerService 的构造函数是导致错误的原因。谢谢! - lincx
1
我帮助你找到了答案,但你接受了另一个答案?因此某个地方的类无法构建。 - jgauffin
显示剩余3条评论

0

当前类型(EX-DI.IBLL.IEmployee)是一个接口,无法被构造。是否缺少类型映射?

答案 -Unity.config.cs中添加以下类型。

public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers

            **container.RegisterType<IEmployee,EmployeeManager>();**
//this could be your interface and the class implementing the interface.

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接