Dependency Injection

本文介绍了依赖注入(Dependency Injection)的概念及其在.NET平台上的实现方式,通过使用接口抽象方法,并结合Ninject框架来实例化不同的类。同时,还详细解释了仓储模式(Repository Pattern)的应用场景,提供了一个具体的数据访问层实现示例。

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>();

转载于:https://www.cnblogs.com/kongshu-612/p/5830770.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值