Dependency Injection

Dependency Injection and Repository Pattern

  1. Dependency Injection, we have a great article here
    and also we have a framework with the name Ninject which is used to help us to build our design.

Let's make things simple. Generally to say, we abstract the methods with Interface, Then we use Instanced class to implement the interface, we can keep more than one versions, e.g. one for
released product, one for Testing, to decouple our class.
Then, if we need these methods, we can include a property with the type Interface, then we initialize this from the constructor. This is so-called Dependency Injection.
for the instance of the class, the framework can shift the efforts.
Ok, Let's take an example.

Code Sample:

Interface code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Models;
using DataAccess;

namespace BusinessLayer
{
    public interface IDataAccessRepository
    {
        IQueryable<Subject> GetAllSubjects();
        Subject GetSubject(int subjectId);
        IQueryable<Course> GetAllCourses();
        IQueryable<Course> GetCoursesBySubject(int subjectId);
        Course GetCourse(int courseId, bool includeEnrollments = true);
        bool CourseExists(int courseId);
        IQueryable<Student> GetAllStudentsWithEnrollments();
        IQueryable<Student> GetAllStudentsSummary();
        IQueryable<Student> GetEnrolledStudentsInCourse(int CourseId);
        Student GetStudentEnrollments(string userName);
        Student GetStudent(string userName);
        Tutor GetTutor(int tutorId);
        bool LoginStudent(string userName, string password);
        bool Insert(Student student);
        bool Update(Student orignalStudent, Student updatedStudent);
        bool DeleteStudent(int studentId);
        int EnrollStudentInCourse(int studentId, int courseId, Enrollment enrollment);
        bool Insert(Course course);
        bool Update(Course orignalCourse, Course updatedCourse);
        bool DeleteCourse(int courseId);
        bool saveAll();
    }
}

The implementaion class code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Models;
using DataAccess;

namespace BusinessLayer
{
    public class DataAccessRepositoy:IDataAccessRepository
    {
        private readonly DataContext _dc;
        public DataAccessRepositoy(DataContext dc)
        {
            _dc = dc;
        }
        public IQueryable<Subject> GetAllSubjects()
        {
            return _dc.Subjects.AsQueryable();
        }
        public Subject GetSubject(int subjectId)
        {
            return _dc.Subjects.Find(subjectId);
        }
        public IQueryable<Course> GetCoursesBySubject(int subjectId)
        {
            return _dc.Courses.Include("Subject").Include("Tutor").Where(e => e.Subject.SubjectId == subjectId).AsQueryable();
        }
        public IQueryable<Course> GetAllCourses()
        {
            return _dc.Courses.Include("Subject").Include("Tutor").AsQueryable();
        }
        public Course GetCourse(int courseId,bool includeEnrollments=true)
        {
            if(includeEnrollments)
            {
                return _dc.Courses
                    .Include("Enrollments")
                    .Include("Subject")
                    .Include("Tutor")
                    .Where(e => e.CourseId == courseId)
                    .SingleOrDefault();
            }
            else
            {
                return _dc.Courses
                    .Include("Subject")
                    .Include("Tutor")
                    .Where(e => e.CourseId == courseId)
                    .SingleOrDefault();
            }
        }
        public bool CourseExists(int courseId)
        {
            return _dc.Courses.Any(e => e.CourseId == courseId);
        }
        public IQueryable<Student> GetAllStudentsWithEnrollments()
        {
            return _dc.Students
                .Include("Enrollments")
                .Include("Enrollments.Course")
                .Include("Enrollments.Course.Subject")
                .Include("Enrollments.Course.Tutor")
                .AsQueryable();
        }
        public IQueryable<Student> GetAllStudentsSummary()
        {
            return _dc.Students.AsQueryable();
        }
        public Student GetStudentEnrollments(string userName)
        {
            return _dc.Students
                .Include("Enrollments")
                .Include("Enrollments.Course")
                .Include("Enrollments.Course.Subject")
                .Include("Enrollments.Course.Tutor")
                .Where(e => e.UserName == userName)
                .SingleOrDefault();
        }
        public Student GetStudent(string userName)
        {
            return _dc.Students
                .Include("Enrollments")
                .Where(e => e.UserName == userName)
                .SingleOrDefault();
        }
        public IQueryable<Student> GetEnrolledStudentsInCourse(int courseId)
        {
            return _dc.Students
                .Include("Enrollments")
                .Where(e => e.Enrollments.Any(t => t.Course.CourseId == courseId))
                .AsQueryable();
        }
        public Tutor GetTutor(int tutorId)
        {
            return _dc.Tutors.Find(tutorId);
        }
        public int EnrollStudentInCourse(int studentId,int courseId,Enrollment enrollment)
        {
            try
            {
                if(_dc.Enrollments.Any(e=>e.Course.CourseId==courseId&&e.Student.StudentId==studentId))
                {
                    return 2;
                }
                _dc.Database.ExecuteSqlCommand("INSERT INTO Enrollments VALUES (@p0,@p1,@p2)", enrollment.EnrollmentDate, courseId.ToString(), studentId.ToString());
                return 1;
            }//we need to log the ouput to log file.
            catch(System.Data.Entity.Validation.DbEntityValidationException dbex)
            {
                foreach(var eve in dbex.EntityValidationErrors)
                {
                    string line = string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                    foreach(var ve in eve.ValidationErrors)
                    {
                        line += string.Format("- Property: \"{0}\", Error: \"{1}\"",
                            ve.PropertyName, ve.ErrorMessage);
                    }
                }
                return 0;
            }
            catch(Exception ex)
            {
                return 0;
            }
        }
        public bool LoginStudent(string userName,string password)
        {
            return _dc.Students.Any(e => e.UserName == userName && e.Password == password);
        }
        public bool Insert(Student student)
        {
            try
            {
                _dc.Students.Add(student);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public bool Update(Student originalStudent, Student updatedStudent)
        {
            _dc.Entry(originalStudent).CurrentValues.SetValues(updatedStudent);
            return true;
        }
        public bool DeleteStudent(int id)
        {
            try
            {
                var entity = _dc.Students.Find(id);
                if(entity!=null)
                {
                    _dc.Students.Remove(entity);
                    return true;
                }
            }
            catch
            {

            }
            return false;
        }
        public bool Insert(Course course)
        {
            try
            {
                _dc.Courses.Add(course);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public bool Update(Course originalCourse, Course updatedCourse)
        {
            _dc.Entry(originalCourse).CurrentValues.SetValues(updatedCourse);
            //have question here for the following actions
            //originalCourse.Subject = updatedCourse.Subject;
            //originalCourse.Tutor = updatedCourse.Tutor;
            return true;
        }
        public bool DeleteCourse(int id)
        {
            try
            {
                var Course = _dc.Courses.Find(id);
                if(Course!=null)
                {
                    _dc.Courses.Remove(Course);
                }
                return true;
            }
            catch
            {

            }
            return false;
        }
        public bool saveAll()
        {
            return _dc.SaveChanges() > 0;
        }
    }
}

we can see the key Point of Dependency Injection , The DataContex depends on the caller of DataAccessRepositoy, Let's see the code below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BusinessLayer;
using Models;
using ViewModels;
using DataAccess;

namespace WebAPIRest.Controllers
{
    public class CoursesController : BaseApiController
    {
        public CoursesController(IDataAccessRepository repo):base(repo)
        { }
    }
}

we can pass different implementation of IDataAccessRepository to fetch different target.
So, we can pass the instance of IDataAccessRepository manually like create in our code, or just using the config with the help of framework like Ninjext.


How to use Ninject Document

OK, we have a brief sample here using Constructor Inection, (Generally, we have constructor injection, property inection, Method injection, ambient context).
we can log these usage in the coming future. Here, we just start up.

as it is stragiforward, we need some where to configure which implementation to use, Then, use it.

Module

they are components to register types, that is to say, we config the relationship between interface and implementation class.
we need to define a class inheriting the NinjectModule. Sample code Here

public class RegisterModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDataAccessRepository>().to<DataAccessRepository>();
    }
}

StandardKernel

It is everything to controller injection. we can user it to load the configuration we make from pre step and get the implementtation class.
code sample:

StandardKernel _Kernal = new StandardKernel();
_Kernal.Load(Assembly.GetExecutingAssembly());
IDataAccessRepository DataAccessRep = _Kernal.Get<IDataAccessRepository>();
posted @   kongshu  阅读(200)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示