【问题标题】:How to write Independency Injection如何编写独立注入
【发布时间】:2020-07-26 06:07:55
【问题描述】:

过去几天我一直在搜索并尝试解决此问题。由于我是 .net/core/c# 的新手,这让我有点困惑。 (我习惯了PHP) 在搜索了我的错误后,我发现这可能是我在代码中遗漏的依赖注入。所以我一直试图在没有运气的情况下将它插入不同的地方。

在这里,我有一个 .net 核心 Web 应用程序 MVC 项目,我一直在尝试将 WebApi 添加到我的项目中。我知道在 .net Core webapi 和 mvc 中应该可以更好地协同工作。 阅读此https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1 后,我不明白我是否应该为所有控制器创建一个新类,或者我是否应该为所有控制器创建一个类,或者实际上将它放在哪里。我应该把它放在 ArticlesController.cs 中吗?

Arcticles 控制器是我拥有的 simples 控制器。我如何为它编写依赖注入?我应该将其写入新课程还是现有课程?

startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;

namespace EducFinder
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddAutoMapper();

            //services.AddTransient<MyService>();
            //services.AddTransient<MyHelper>();
            services.AddDbContext<DbContext>(optionsBuilder => optionsBuilder.UseSqlServer(Configuration.GetConnectionString("AdminConnectionstring")));//add
            services.AddControllersWithViews();
            //services.AddControllers();
            //services.AddScoped<IMyArticles, MemoryRepository>();
            //services.AddDbContext<DbContext>(op => op.UseSqlServer(Configuration.GetConnectionString("AdminConnectionstring")));//add
           
            //services.AddScoped<IRepository, MemoRepostory>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                //endpoints.MapControllerRoute(name: "api", pattern: "api/{controller}/{id?}");
                //endpoints.MapControllerRoute(name: "api", pattern: "api/{controller=Admin}");
                endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");

            });
        }
    }
}

Articles.cs

using System;
using System.Collections.Generic;
namespace EducFinder.Models
{
    
    public partial class Articles 
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Summary { get; set; }
        public DateTime Createdon { get; set; }
        public string Active { get; set; }
        public int? Userid { get; set; }
        public virtual Users User { get; set; }
    }
}

ArticlesController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using EducFinder.Models;

namespace EducFinder.api
{
    
    [Route("api/[controller]")]
    [ApiController]
    public class ArticlesController : ControllerBase
    {
        private readonly DB_A64E0D_yiyote3945Context _context;

        public ArticlesController(DB_A64E0D_yiyote3945Context context)
        {
            _context = context;
        }

        // GET: api/Articles
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Articles>>> GetArticles()
        {
            return await _context.Articles.ToListAsync();
        }

        // GET: api/Articles/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Articles>> GetArticles(int id)
        {
            var articles = await _context.Articles.FindAsync(id);

            if (articles == null)
            {
                return NotFound();
            }

            return articles;
        }

        // PUT: api/Articles/5
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutArticles(int id, Articles articles)
        {
            if (id != articles.Id)
            {
                return BadRequest();
            }

            _context.Entry(articles).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ArticlesExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Articles
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPost]
        public async Task<ActionResult<Articles>> PostArticles(Articles articles)
        {
            _context.Articles.Add(articles);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetArticles", new { id = articles.Id }, articles);
        }

        // DELETE: api/Articles/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Articles>> DeleteArticles(int id)
        {
            var articles = await _context.Articles.FindAsync(id);
            if (articles == null)
            {
                return NotFound();
            }

            _context.Articles.Remove(articles);
            await _context.SaveChangesAsync();

            return articles;
        }

        private bool ArticlesExists(int id)
        {
            return _context.Articles.Any(e => e.Id == id);
        }
    }
}

DB_A64E0D_yiyote3945Context.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace EducFinder.Models
{
    public partial class DB_A64E0D_yiyote3945Context : DbContext
    {
    public DB_A64E0D_yiyote3945Context()
    {
    }

    public DB_A64E0D_yiyote3945Context(DbContextOptions<DB_A64E0D_yiyote3945Context> options)
        : base(options)
    {
    }

    public virtual DbSet<Articles> Articles { get; set; }
//...more code
    public virtual DbSet<Users> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
            optionsBuilder.UseSqlServer("Data Source=cool.com;Initial Catalog=DB_Coolstuff;User Id=DB_CoolStuff_admin;Password=IDidNotForgetMyPassword;");
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    {
        modelBuilder.Entity<Articles>(entity =>
        {
            entity.Property(e => e.Id).HasColumnName("id");

            entity.Property(e => e.Active)
                .HasColumnName("active")
                .HasMaxLength(1)
                .IsFixedLength();

            entity.Property(e => e.Createdon)
                .HasColumnName("createdon")
                .HasColumnType("datetime")
                .HasDefaultValueSql("(getdate())");

            entity.Property(e => e.Summary)
                .HasColumnName("summary")
                .HasColumnType("text");

            entity.Property(e => e.Title)
                .HasColumnName("title")
                .HasMaxLength(60)
                .IsUnicode(false);

            entity.Property(e => e.Userid).HasColumnName("userid");

            entity.HasOne(d => d.User)
                .WithMany(p => p.Articles)
                .HasForeignKey(d => d.Userid)
                .HasConstraintName("FK_Articles_Users");
        });

        //... Much more code

        modelBuilder.Entity<Users>(entity =>
        {
            entity.Property(e => e.Id).HasColumnName("id");

            entity.Property(e => e.Active)
                .HasColumnName("active")
                .HasMaxLength(1)
                .IsFixedLength();

            entity.Property(e => e.Createdon)
                .HasColumnName("createdon")
                .HasColumnType("datetime")
                .HasDefaultValueSql("(getdate())");

            entity.Property(e => e.Email)
                .HasColumnName("email")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Fbtoken)
                .HasColumnName("fbtoken")
                .HasMaxLength(50);

            entity.Property(e => e.Fbuserid)
                .HasColumnName("fbuserid")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Feideuserid)
                .HasColumnName("feideuserid")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Guserid)
                .HasColumnName("guserid")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Modifiedon)
                .HasColumnName("modifiedon")
                .HasColumnType("datetime");

            entity.Property(e => e.Name)
                .HasColumnName("name")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Password)
                .HasColumnName("password")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Salt)
                .HasColumnName("salt")
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.Securityrole)
                .HasColumnName("securityrole")
                .HasMaxLength(1)
                .IsFixedLength();
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}

当我尝试访问 WebAPi 时,我收到此错误:

【问题讨论】:

  • 那么你的问题是什么?你有什么错误吗?
  • 不,我没有收到任何其他错误。好吧,当我把依赖注入错误的地方时,我得到一个错误。但正如我用粗体写的那样,我不知道将依赖注入放在哪里。它应该在新班级还是现有班级中?
  • 你已经正确实现了,我没有看到任何问题。您也可以以这种方式使用。 using (var context = serviceProvider.GetService&lt;YourDbContext&gt;()) { ... }
  • @viveknuna 我想我们现在正在接近一些事情。因为我收到 GetService 错误。因为我收到错误:Iservicecollection 不包含 getservice 的定义 我添加了 NuGet:Microsoft.Extensions.DependencyInjection.Abstractions 和 Microsoft.Extensions.DependencyInjection。但是仍然可以使用 GetService 来解决这个问题...
  • 你的问题标题比帖子有趣得多。

标签: c# asp.net-mvc asp.net-core asp.net-web-api dependency-injection


【解决方案1】:

您永远不会在ConfigureServices 中注册DB_A64E0D_yiyote3945Context。只有一个AddDbContext 调用,基类DbContext 作为泛型类型参数。相反,您应该在此处添加自己的 DbContext(s):

public void ConfigureServices(IServiceCollection services)
{
    // More stuff here.
    services.AddDbContext<DB_A64E0D_yiyote3945Context>(optionsBuilder => optionsBuilder.UseSqlServer(Configuration.GetConnectionString("AdminConnectionstring")));
    // ...
}

根据要求对泛型进行短途旅行:

在编写generic 函数、类等时,您基本上是在编写蓝图。稍后在使用该蓝图时,您必须提供要与该蓝图一起使用的实际 Type。那是你的generic type parameter。例如。 List&lt;T&gt; 类有一个称为T 的泛型类型参数。在runtime,为作为类型参数提供的每种不同类型生成一个指定的类。因此,对于List&lt;int&gt;List&lt;string&gt; 中的每一个,运行时都会生成适当的代码以从蓝图List&lt;T&gt; 运行。这同样适用于像AddDbContext&lt;TContext&gt; 这样的方法。对于每个TContext,都会生成一个专门的版本。

这是泛型的简短版本,但它至少应该为您提供基础知识。如果您知道C++,您可能想将其与templates 进行比较,但这实际上是另一回事(但同样可能会给您一些线索)

【讨论】:

    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多