Dependency injection 如何在ASP.Net核心MVC中向服务中注入repo

Dependency injection 如何在ASP.Net核心MVC中向服务中注入repo,dependency-injection,asp.net-core-3.1,Dependency Injection,Asp.net Core 3.1,我有一个很奇怪的问题。 我已经为名为PageHits的数据库集定义了一个存储库 这是接口: public interface IPageHitRepo { IQueryable<PageHit> PageHits { get; } void AddPageHit(PageHit pageHit); void SaveChanges(); } 然后,PageHitService的顶部如下所示: services.AddScoped<IPageHitRep

我有一个很奇怪的问题。
我已经为名为PageHits的数据库集定义了一个存储库

这是接口:

public interface IPageHitRepo
{
    IQueryable<PageHit> PageHits { get; }
    void AddPageHit(PageHit pageHit);
    void SaveChanges();
}
然后,PageHitService的顶部如下所示:

services.AddScoped<IPageHitRepo, PageHitRepo>();
public interface IPageHitService
{
    // Default implimentation overridden in PageHitService.
    Task Invoke(IServiceProvider sp) => Task.FromResult(true); 
    Task EmailSiteHitNotification(PageHit pageHit, IServiceProvider sp);
    Task LogPageHitToDB(PageHit pageHit, IServiceProvider sp);
}
public class PageHitService : IPageHitService
{
    private IPageHitRepo _pageHitRepo;
    public PageHitService(IPageHitRepo pageHitRepo)
    {
        _pageHitRepo = pageHitRepo;
    }
    
    public async Task Invoke(IServiceProvider sp)
    {
        HttpContext httpContext =
            sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
        IWebHostEnvironment env = sp.GetRequiredService<IWebHostEnvironment>();
        IConfiguration config = sp.GetRequiredService<IConfiguration>();
        // _context = sp.GetRequiredService<CtasContext>();

        bool visitSet =
            !string.IsNullOrEmpty(httpContext.Session.GetString("VisitSet"));
调用是静态的,因为我在沿着工厂路线胡闹。 我不能调用非静态方法,所以我必须实例化一个实例来调用API中的2个方法。 现在没有任何东西是静态的,所以我将注释掉这一行,并尝试直接调用这些方法

下面是完整的课程:

public class PageHitService : IPageHitService
{
    private IPageHitRepo _pageHitRepo;
    
    public PageHitService(IPageHitRepo pageHitRepo)
    {
        _pageHitRepo = pageHitRepo;
    }
    
    public async Task Invoke(IServiceProvider sp)
    {
        HttpContext httpContext =
            sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
        IWebHostEnvironment env = sp.GetRequiredService<IWebHostEnvironment>();
        IConfiguration config = sp.GetRequiredService<IConfiguration>();
        // _context = sp.GetRequiredService<CtasContext>();

        bool visitSet =
            !string.IsNullOrEmpty(httpContext.Session.GetString("VisitSet"));

        PageHit PageHit = new PageHit
        {
            SessionID = httpContext.Session.Id,
            UserIP = httpContext.Connection.RemoteIpAddress.ToString(),
            EnvironmentName = env.EnvironmentName,
            Url = httpContext.Request.PathBase + httpContext.Request.Path,
            ReferrerUrl = httpContext.Request.Headers["Referer"].ToString(),
            DateTime = DateTime.Now
        };

        PageHitService pageHitService = new PageHitService();
        bool logPageHitsOn = bool.Parse(config["LogPageHitsOn"]);
        bool emailSiteHitNotificationsOn = bool.Parse(config["EmailSiteHitNotificationsOn"]);
        if (!visitSet)
        {
            // create session
            httpContext.Session.SetString("VisitSet", "true");

            // Emails (1st visit of session)
            if (emailSiteHitNotificationsOn)
            {
                await pageHitService.EmailSiteHitNotification(PageHit, sp);
            }
        }

        // Logs all PageHits to DB.
        if (logPageHitsOn)
        {
            await pageHitService.LogPageHitToDB(PageHit, sp);
        }
    }

    public async Task EmailSiteHitNotification(PageHit pageHit,
        IServiceProvider sp)
    {
        IEmailService emailService = sp.GetRequiredService<IEmailService>();

        StringBuilder body = new StringBuilder();
        body.AppendFormat($"<b>SessionID:</b> {pageHit.SessionID}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>User Ip:</b> {pageHit.UserIP}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>Environment:</b> {pageHit.EnvironmentName}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>Url (Page Hit):</b> {pageHit.Url}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>ReferrerUrl:</b> {pageHit.ReferrerUrl}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>DateTime:</b> {pageHit.DateTime}");
        body.Append("<br /><br />");

        string subject = "CTAS Hit Notification";

        await emailService.SendEmail(body.ToString(), subject);
    }

    public async Task LogPageHitToDB(PageHit pageHit,
        IServiceProvider sp)
    {
        CtasContext context = sp.GetRequiredService<CtasContext>();
        await context.PageHits.AddAsync(pageHit);
        await context.SaveChangesAsync();
    }
}
公共类PageHitService:IPageHitService
{
私人IPageHitRepo_pageHitRepo;
公共PageHitService(IPageHitRepo pageHitRepo)
{
_pageHitRepo=pageHitRepo;
}
公共异步任务调用(IServiceProvider sp)
{
HttpContext HttpContext=
sp.GetRequiredService().HttpContext;
IWebHostenEnvironment env=sp.GetRequiredService();
IConfiguration config=sp.GetRequiredService();
//_context=sp.GetRequiredService();
布尔参观酒店=
!string.IsNullOrEmpty(httpContext.Session.GetString(“VisitSet”));
PageHit PageHit=新的PageHit
{
SessionID=httpContext.Session.Id,
UserIP=httpContext.Connection.RemoteIpAddress.ToString(),
EnvironmentName=env.EnvironmentName,
Url=httpContext.Request.PathBase+httpContext.Request.Path,
refererUrl=httpContext.Request.Headers[“Referer”].ToString(),
DateTime=DateTime.Now
};
PageHitService PageHitService=新的PageHitService();
bool logPageHitsOn=bool.Parse(config[“logPageHitsOn”]);
bool-emailSiteHitNotificationsOn=bool.Parse(配置[“emailSiteHitNotificationsOn]”);
如果(!visitSet)
{
//创建会话
httpContext.Session.SetString(“VisitSet”、“true”);
//电子邮件(课程第一次访问)
如果(emailSiteHitNotificationsOn)
{
等待pageHitService.EmailSiteHitNotification(PageHit,sp);
}
}
//将所有页面点击记录到数据库中。
if(logPageHitsOn)
{
等待pageHitService.LogPageHitToDB(PageHit,sp);
}
}
公共异步任务EmailSiteHitNotification(PageHit PageHit,
IServiceProvider sp)
{
IEmailService emailService=sp.GetRequiredService();
StringBuilder主体=新的StringBuilder();
AppendFormat($“SessionID:{pageHit.SessionID}”);
正文。追加(“

”); AppendFormat($“用户Ip:{pageHit.UserIP}”); 正文。追加(“

”); AppendFormat($“环境:{pageHit.EnvironmentName}”); 正文。追加(“

”); AppendFormat($“Url(页面命中):{pageHit.Url}”); 正文。追加(“

”); AppendFormat($“refererURL:{pageHit.refererURL}”); 正文。追加(“

”); AppendFormat($“DateTime:{pageHit.DateTime}”); 正文。追加(“

”); string subject=“CTAS命中通知”; 等待emailService.SendEmail(body.ToString(),subject); } 公共异步任务日志PageHitToDB(PageHit PageHit, IServiceProvider sp) { CtasContext context=sp.GetRequiredService(); wait context.PageHits.AddAsync(pageHit); wait context.saveChangesSync(); } }
您的代码中出现了一些您在问题中没有显示的内容。就目前而言,您的问题是不可重现的。因此,你的问题需要详细或清晰。您是否可能没有制作与代码完全相同的副本?可能还有一个名为
IPageHitService
的(基类)?举个例子,看看这个。@Steven-谢谢你的关注。此服务没有基类。我有一个基本控制器和一个调用服务的基本页面模型。如果我添加一个私有构造函数,编译错误就会消失。这是因为我在IPageHitService的一个接口成员上有一个默认实现吗?我不同意所有这些。GetService可能会意外地从根容器中提取内容,这可能解释了为什么会得到ObjectDisposedEx。具有20个依赖项的基类可能表明该类存在问题。使用IServiceProvider应该仅限于合成根。很好,它正在工作。我能推荐一本关于依赖性的好书给你以拓宽你的知识面吗?依赖注入原则、实践和模式(由我合著)。
services.AddScoped<IPageHitService, PageHitService>();
public class BaseController : Controller
    {
        public BaseController(IServiceProvider sp)
        {
            IPageHitService pageHitService = sp.GetRequiredService<IPageHitService>();
            // pageHitService.Invoke(sp).Await();
            pageHitService.Invoke(sp).Wait();
        }

        #region Callbacks if you use AsyncMethod.Await() extension method.
        private void Completed()
        {
            Console.WriteLine("Completed pageHitService.Invoke from BaseController");
        }

        private void HandleError(Exception ex)
        {
            // TODO: Log Error to DB;
        }
        #endregion

    }

public class BasePageModel : PageModel
{
     public BasePageModel(IServiceProvider sp)
    {
        IPageHitService pageHitService = sp.GetRequiredService<IPageHitService>();
        // pageHitService.Invoke(sp).Await();
        pageHitService.Invoke(sp).Wait();
    }

    #region Callbacks if you use AsyncMethod.Await() extension method.
    private void Completed()
    {
        Console.WriteLine("Completed pageHitService.Invoke from BaseController");
    }

    private void HandleError(Exception ex)
    {
        // TODO: Log Error to DB;
    }
    #endregion
}
PageHitService pageHitService = new PageHitService();
public class PageHitService : IPageHitService
{
    private IPageHitRepo _pageHitRepo;
    
    public PageHitService(IPageHitRepo pageHitRepo)
    {
        _pageHitRepo = pageHitRepo;
    }
    
    public async Task Invoke(IServiceProvider sp)
    {
        HttpContext httpContext =
            sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
        IWebHostEnvironment env = sp.GetRequiredService<IWebHostEnvironment>();
        IConfiguration config = sp.GetRequiredService<IConfiguration>();
        // _context = sp.GetRequiredService<CtasContext>();

        bool visitSet =
            !string.IsNullOrEmpty(httpContext.Session.GetString("VisitSet"));

        PageHit PageHit = new PageHit
        {
            SessionID = httpContext.Session.Id,
            UserIP = httpContext.Connection.RemoteIpAddress.ToString(),
            EnvironmentName = env.EnvironmentName,
            Url = httpContext.Request.PathBase + httpContext.Request.Path,
            ReferrerUrl = httpContext.Request.Headers["Referer"].ToString(),
            DateTime = DateTime.Now
        };

        PageHitService pageHitService = new PageHitService();
        bool logPageHitsOn = bool.Parse(config["LogPageHitsOn"]);
        bool emailSiteHitNotificationsOn = bool.Parse(config["EmailSiteHitNotificationsOn"]);
        if (!visitSet)
        {
            // create session
            httpContext.Session.SetString("VisitSet", "true");

            // Emails (1st visit of session)
            if (emailSiteHitNotificationsOn)
            {
                await pageHitService.EmailSiteHitNotification(PageHit, sp);
            }
        }

        // Logs all PageHits to DB.
        if (logPageHitsOn)
        {
            await pageHitService.LogPageHitToDB(PageHit, sp);
        }
    }

    public async Task EmailSiteHitNotification(PageHit pageHit,
        IServiceProvider sp)
    {
        IEmailService emailService = sp.GetRequiredService<IEmailService>();

        StringBuilder body = new StringBuilder();
        body.AppendFormat($"<b>SessionID:</b> {pageHit.SessionID}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>User Ip:</b> {pageHit.UserIP}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>Environment:</b> {pageHit.EnvironmentName}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>Url (Page Hit):</b> {pageHit.Url}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>ReferrerUrl:</b> {pageHit.ReferrerUrl}");
        body.Append("<br /><br />");
        body.AppendFormat($"<b>DateTime:</b> {pageHit.DateTime}");
        body.Append("<br /><br />");

        string subject = "CTAS Hit Notification";

        await emailService.SendEmail(body.ToString(), subject);
    }

    public async Task LogPageHitToDB(PageHit pageHit,
        IServiceProvider sp)
    {
        CtasContext context = sp.GetRequiredService<CtasContext>();
        await context.PageHits.AddAsync(pageHit);
        await context.SaveChangesAsync();
    }
}