为什么我的Funq容器无法正常工作?

Mik*_*osa 4 c# asp.net-mvc servicestack

当我点击试图访问数据库的代码时,我得到一个空引用异常.

这是在global.asax中,我已经逐步完成调试器并且正在执行此代码.

public class MvcApplication : System.Web.HttpApplication
{
    public class DmsAppHost : AppHostBase
    {
        public DmsAppHost() : base("API", typeof(AppUsersService).Assembly) { }

        public override void Configure(Funq.Container container)
        {
            var dbConnectionFactory = new OrmLiteConnectionFactory("Server=localhost;Port=5432;User Id=dms; Password=dms; Database=dms", PostgreSqlDialect.Provider);
            container.Register<IDbConnectionFactory>(dbConnectionFactory);
            container.RegisterAutoWiredAs<AppUserRepository, IAppUserRepository>();
        }
    }

    protected void Application_Start()
    {
        new DmsAppHost().Init();

        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BootstrapSupport.BootstrapBundleConfig.RegisterBundles(System.Web.Optimization.BundleTable.Bundles);
    }

}
Run Code Online (Sandbox Code Playgroud)

当我点击这段代码时(使用(var db = DbConnectionFactory.OpenDbConnection()))我得到一个NullReferenceException.

你调用的对象是空的.

public class AppUserRepository : IAppUserRepository
{
    public IDbConnectionFactory DbConnectionFactory { get; set; }

    public AppUser GetAppUserByUsername(string username)
    {
        AppUser appUser;
        using (var db = DbConnectionFactory.OpenDbConnection())
        {
            appUser = db.QuerySingle<AppUser>(new { username });
        }
        return appUser;
    }
}
Run Code Online (Sandbox Code Playgroud)

我是否认为我的Connection出了问题,或者有什么我不能正确使Funq工作?

Dar*_*rov 9

您已经展示了一些Funq容器配置,它将依赖项注入到您的AppUserRepository类中.但是你没有说明这个课程的使用方式和地点.由于您的问题被标记为asp.net-mvc我认为这发生在ASP.NET MVC控制器操作中.有点像:

public class HomeController: Controller
{
    private readonly IAppUserRepository repo;
    public HomeController(IAppUserRepository repo)
    {
        this.repo = repo;
    }

    public ActionResult Index(int id)
    {
        var model = this.repo.Get(id);
        return View(model);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要在ASP.NET MVC中使用依赖项注入框架,则必须编写一个dependency resolver将注入到控制器中的自定义项.

那么让我们继续为Funq写一个:

public class FunqDependencyResolver : IDependencyResolver
{
    private readonly ContainerResolveCache cache;
    public FunqDependencyResolver(Container container)
    {
        this.cache = new ContainerResolveCache(container);
        var controllerTypes =
            (from type in Assembly.GetCallingAssembly().GetTypes()
             where typeof(IController).IsAssignableFrom(type)
             select type).ToList();
        container.RegisterAutoWiredTypes(controllerTypes);
    }

    public object GetService(Type serviceType)
    {
        return this.cache.CreateInstance(serviceType, true);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<object>();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以注册Application_Start:

protected void Application_Start()
{
    var container = new Container();
    var dbConnectionFactory = new OrmLiteConnectionFactory("Server=localhost;Port=5432;User Id=dms; Password=dms; Database=dms", PostgreSqlDialect.Provider);
    container.Register<IDbConnectionFactory>(dbConnectionFactory);
    container.RegisterAutoWiredAs<AppUserRepository, IAppUserRepository>();
    DependencyResolver.SetResolver(new FunqDependencyResolver(container));

    AreaRegistration.RegisterAllAreas();

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BootstrapSupport.BootstrapBundleConfig.RegisterBundles(System.Web.Optimization.BundleTable.Bundles);
}
Run Code Online (Sandbox Code Playgroud)

另外我建议你为你的AppUserRepository类使用构造函数注入,因为这DbConnectionFactory是一个绝对必需的依赖项,这个类可以正常工作:

public class AppUserRepository : IAppUserRepository
{
    private readonly IDbConnectionFactory dbConnectionFactory;
    public class AppUserRepository(IDbConnectionFactory dbConnectionFactory)
    {
        this.dbConnectionFactory = dbConnectionFactory;
    }

    public AppUser GetAppUserByUsername(string username)
    {
        AppUser appUser;
        using (var db = this.dbConnectionFactory.OpenDbConnection())
        {
            appUser = db.QuerySingle<AppUser>(new { username });
        }
        return appUser;
    }
}
Run Code Online (Sandbox Code Playgroud)