Summary of Web System Framework Based on.net EF6 MVC5+WEB Api-Project Dependency Injection

Keywords: C# Unity MySQL SQL Database

  1. brief introduction

Dependency injection is mainly a structural model, focusing on the structure between classes. Its purpose is to achieve the principle of minimum knowledge and composite reuse in design principles, reduce internal dependency, perform a single responsibility, and ultimately strong decoupling. The best implementation of Dependency Injection at present is the Dependency Injection Container.

Unity is a lightweight and extensible Dependency Injection container developed by Microsoft Patterns & Practices team. It supports three common methods of dependency injection: Constructor Injection, Property Injection and Method Call I Injection. Njection.

This project is based on Unity to reduce internal dependency and achieve project decoupling. Open source based on LGPL protocol.

 

2. Project source code

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;

namespace ShiQuan.Unity
{
    /// <summary>
    /// Unity Auxiliary Objects
    /// </summary>
    public class UnityHelper
    {
        #region Single case

        private static readonly UnityHelper _instance = new UnityHelper();
        /// <summary>
        /// Unity Auxiliary Objects
        /// </summary>
        public static UnityHelper Instance
        {
            get
            {
                return _instance;
            }
        }
        #endregion

        private readonly IUnityContainer _container = new UnityContainer();
        /// <summary>
        /// Getting containers
        /// </summary>
        public IUnityContainer Container
        {
            get { return _container; }
        }
        private UnityHelper()
        {
            var configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;
            if (configuration != null)
            {
                configuration.Configure(_container);
            }
        }

        #region Get the concrete implementation class of the corresponding interface
        /// <summary>
        /// Get the implementation class(Default mapping)
        /// </summary>
        /// <typeparam name="T">Interface type</typeparam>
        /// <returns>Interface</returns>
        public T GetResolve<T>()
        {
            return _container.Resolve<T>();
        }
        /// <summary>
        /// Get the implementation class(Default mapping)Parametric
        /// </summary>
        /// <typeparam name="T">Interface type</typeparam>
        /// <param name="parameter">parameter</param>
        /// <returns>Interface</returns>
        public T GetResolve<T>(params ParameterOverride[] parameter)
        {
            return _container.Resolve<T>(parameter);
        }
        /// <summary>
        /// Get the implementation class(Specified mapping)Parametric
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="parameter"></param>
        /// <returns>Interface</returns>
        public T GetResolve<T>(string name, params ParameterOverride[] parameter)
        {
            return _container.Resolve<T>(name, parameter);
        }
        #endregion

        #region Determine whether the interface is registered
        /// <summary>
        /// Determine whether the interface is implemented
        /// </summary>
        /// <typeparam name="T">Interface type</typeparam>
        /// <returns>bool</returns>
        public bool IsRegistered<T>()
        {
            return _container.IsRegistered<T>();
        }
        /// <summary>
        /// Determine whether the interface is implemented
        /// </summary>
        /// <typeparam name="T">Interface type</typeparam>
        /// <param name="name">Mapping name</param>
        /// <returns></returns>
        public bool IsRegistered<T>(string name)
        {
            return _container.IsRegistered<T>(name);
        }
        #endregion
    }
}

 

Source address: https://gitee.com/ShiQuan25/ShiQuan.Unity

3. Call examples

The following demonstrates an example of calling this program:

First, we create a data manipulation infrastructure project, define the IDataBase interface, and define a method to get the name.

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

namespace ShiQuan.DataAccess
{
    /// <summary>
    /// Define interfaces
    /// </summary>
    public interface IDatabase
    {
        string Name { get; }
    }
}

 

Create the SQL SERVER project and define SqlDataBase to implement IDatabase interface.

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

namespace ShiQuan.DataServer
{
    /// <summary>
    /// Realization
    /// </summary>
    public class SqlDataBase : IDatabase
    {
        public string Name
        {
            get { return "SqlDataBase"; }
        }
    }
}

 

Create MySql project and define MySqlDataBase to implement IDatabase interface.

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

namespace ShiQuan.DataMySql
{
    /// <summary>
    /// Realization
    /// </summary>
    public class MySqlDataBase : IDatabase
    {
        public string Name
        {
            get { return "MySqlDataBase"; }
        }
    }
}

Create a data operation factory project and define the DataFactory implementation to call different implementation classes based on parameters.

using ShiQuan.DataAccess;
using ShiQuan.DataMySql;
using ShiQuan.DataServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShiQuan.DataRepository
{
    /// <summary>
    /// Data Factory
    /// </summary>
    public class DataFactory
    {
        /// <summary>
        /// Getting Data Operating Objects
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IDatabase GetDataBase(string name)
        {
            switch (name)
            {
                case "MySql":
                    {
                        return new MySqlDataBase();
                    }
                case "SqlServer":
                default:
                    {
                        return new SqlDataBase();
                    }
            }
            
        }
    }
}

Create Console program for testing

using ShiQuan.DataServer;
using ShiQuan.DataMySql;
using ShiQuan.Unity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShiQuan.DataAccess;
using ShiQuan.DataRepository;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Instance and call Sql Server...");
            IDatabase sqlserver = DataFactory.GetDataBase("SqlServer");
            Console.WriteLine(sqlserver.Name);

            Console.WriteLine("Instance and call MySql...");
            IDatabase mysql = DataFactory.GetDataBase("MySql");
            Console.WriteLine(mysql.Name);

            Console.ReadLine();
        }
        
    }
}

The project structure is roughly as follows:

Running results:

Unity call

Suppose at this time, if we need to implement other database operations and IDatabase interface, we have to modify and adjust the data operation factory project in addition to adding other database operation items.

However, if our data operation factory project changes to dependency injection mode, the factory project does not need to refer to the SQL SERVER project, MySQL project and other database operation projects. Without changing the factory project, the main program can directly add the corresponding operation items and classes in the configuration file to achieve oriented. Interface development, reduce internal dependencies, and achieve project decoupling.

Project Add Package

 

Additional configuration for main program configuration files (App.Config or Web.Config)

<configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration" />
  </configSections>

 

Configuration interface, interface implementation object

 

<unity>
    <typeAliases>
      <typeAlias alias="IDatabase" type="ShiQuan.DataAccess.IDatabase,ShiQuan.DataAccess" />
      <typeAlias alias="SqlServer" type="ShiQuan.DataServer.SqlDataBase,ShiQuan.DataServer" />
      <typeAlias alias="MySql" type="ShiQuan.DataMySql.MySqlDataBase,ShiQuan.DataMySql" />
    </typeAliases>
    <containers>
      <container>
        <type type="IDatabase" mapTo="SqlServer" name="SqlServer"></type >
        <type type="IDatabase" mapTo="MySql" name="MySql"></type >
      </container>
    </containers>
  </unity>

Factory Project Instance Call

 

/// <summary>
        /// Getting Data Operating Objects
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IDatabase GetDataBase(string name)
        {
            //switch (name)
            //{
            //    case "MySql":
            //        {
            //            return new MySqlDataBase();
            //        }
            //    case "SqlServer":
            //    default:
            //        {
            //            return new SqlDataBase();
            //        }
            //}
            return ShiQuan.Unity.UnityHelper.Instance.GetResolve<IDatabase>(name);
        }

Running test results achieve the same effect as factory mode, and have stronger scalability, project decoupling, and reduce project dependence.

 

At this point, the project is introduced, more exciting, and listen to the next decomposition!

Posted by Najjar on Tue, 10 Sep 2019 00:48:19 -0700