.NET领域最为流行的IOC框架之一Autofac

 

一、前言

Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也是用的Autofac。

Orchad和Nopcommerce在用Autofac的时候进行封装,看过源码的都知道Autafac使用简单,功能强大。

建议下载Orchad和Nopcommerce学习下源码:附上下载地址

http://www.orchardproject.net/

http://www.nopcommerce.com/

和其他IOC对比:

Unity:微软patterns&practicest团队开发的IOC依赖注入框架,支持AOP横切关注点。

MEF(Managed Extensibility Framework):是一个用来扩展.NET应用程序的框架,可开发插件系统。

Spring.NET:依赖注入、面向方面编程(AOP)、数据访问抽象,、以及ASP.NET集成。

PostSharp:实现静态AOP横切关注点,使用简单,功能强大,对目标拦截的方法无需任何改动。

Autofac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

下面介绍Autofac的使用

二、Autofac使用

新建一个mvc的项目,使用nuget安装Autofac,需要安装Autofac和Autofac ASP.NET MVC5 Intergration

安装完成后引用里面就多了Autofac.dll和Autofac.Intergration.MVC,如果是在webApi里使用Autofac需要安装Autofac ASP.NET Web API2.2 Intergration 才可以。

新建一个person实体类

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

新建一个person仓储接口

    public interface IPersonRepository
    {
        IEnumerable<Person> GetAll();
        Person Get(int id);
        Person Add(Person item);
        bool Update(Person item);
        bool Delete(int id);
    }

新建实现

 public class PersonRepository : IPersonRepository
    {
        List<Person> person = new List<Person>();

        public PersonRepository()
        {
            Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中国上海" });
        }
        public IEnumerable<Person> GetAll()
        {
            return person;
        }
        public Person Get(int id)
        {
            return person.Find(p => p.Id == id);
        }
        public Person Add(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            person.Add(item);
            return item;
        }
        public bool Update(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = person.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            person.RemoveAt(index);
            person.Add(item);
            return true;
        }
        public bool Delete(int id)
        {
            person.RemoveAll(p => p.Id == id);
            return true;
        }
    }

Global属性注入

 public class MvcApplication : System.Web.HttpApplication
    {
        private void SetupResolveRules(ContainerBuilder builder)
        {
            builder.RegisterType<PersonRepository>().As<IPersonRepository>();
        }
        protected void Application_Start()
        {
            var builder = new ContainerBuilder();
            SetupResolveRules(builder);
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

最好获取数据结果;

三、总结

文中只是给出了一个简单的注入实现,剩下的可以自己去研究下,构造函数注入,方法注入

泛型注入,所有程序集注入,都可以看下,

也可以把文章开头的两个开源的项目下载下来研究里面的Autofac注入方式。

WebAPI2使用Autofac实现IOC属性注入完美解决方案

 

一、前言

只要你是.NETer你一定IOC,IOC里面你也会一定知道Autofac,上次说了在MVC5实现属性注入,今天实现在WebApi2实现属性注入,顺便说一下autofac的程序集的注入方式,都会在后面的代码里面有提现

在WebAPI2使用Autofac注入的时候大多数人会出现如下问题:

未能加载文件或程序集“System.Web.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

截图如下:

这个是Autofac强依赖造成的,比较坑的。解决办法如下。

Nuget添加Microsoft.AspNet.WebApi

或通过NuGet 程序包管理器控制台添加:

Install-Package Microsoft.AspNet.WebApi

Update-Package Microsoft.AspNet.WebApi -reinstall(存在)

原因:我们新建的是一个空的MVC项目,缺少引用

先上个结构图,结构图只是为了说明webAPI如何简单使用Autofac实现属性注入。

属性注入存在安全隐患,官方建议使用构造函数注入。

下面说下具体实现:

二、代码实现

1、新建一个WebAPI.Entity类库,新建一个Person.cs类

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

2、新建WebAPI.IRepository类库,新建一个IPersonRepository类

    public interface IPersonRepository
    {
        List<Person> GetAll();
        Person Get(int id);
        Person Add(Person item);
        bool Update(Person item);
        bool Delete(int id);
    }

3、新建WebAPI.Repository类库,新建一个PersonRepository类实现IPersonRepository接口

public class PersonRepository : IPersonRepository
    {
        List<Person> person = new List<Person>();

        public PersonRepository()
        {
            Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中国上海" });
        }
        public List<Person> GetAll()
        {
            return person;
        }
        public Person Get(int id)
        {
            return person.Find(p => p.Id == id);
        }
        public Person Add(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            person.Add(item);
            return item;
        }
        public bool Update(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = person.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            person.RemoveAt(index);
            person.Add(item);
            return true;
        }
        public bool Delete(int id)
        {
            person.RemoveAll(p => p.Id == id);
            return true;
        }
    }

4、新建WebAPI.IServices类库,新建IPersonServices接口

    public interface IPersonServices
    {
        List<Person> GetAll();
    }

5、IPersonServices接口在WebAPI.Services类库里面PersonServices实现

    public class PersonServices : IPersonServices
    {
        //程序集属性注入
        public IPersonRepository iPerson;

        public List<Person> GetAll()
        {
            return iPerson.GetAll();
        }
    }

6、新建一个WebAPI项目WebAPI,新建AutoFacBootStrapper类,nuget安装autofac

public class AutoFacBootStrapper
    {
        public static void CoreAutoFacInit()
        {
            var builder = new ContainerBuilder();
            HttpConfiguration config = GlobalConfiguration.Configuration;

            SetupResolveRules(builder);

            ////注册所有的Controllers
            //builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            //注册所有的ApiControllers
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            var container = builder.Build();
            //注册api容器需要使用HttpConfiguration对象
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

        private static void SetupResolveRules(ContainerBuilder builder)
        {
            //WebAPI只用引用services和repository的接口,不用引用实现的dll。
            //如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
            var iServices = Assembly.Load("WebAPI.IServices");
            var services = Assembly.Load("WebAPI.Services");
            var iRepository = Assembly.Load("WebAPI.IRepository");
            var repository = Assembly.Load("WebAPI.Repository");

            //根据名称约定(服务层的接口和实现均以Services结尾),实现服务接口和服务实现的依赖
            builder.RegisterAssemblyTypes(iServices, services)
              .Where(t => t.Name.EndsWith("Services"))
              .AsImplementedInterfaces();

            //根据名称约定(数据访问层的接口和实现均以Repository结尾),实现数据访问接口和数据访问实现的依赖
            builder.RegisterAssemblyTypes(iRepository, repository)
              .Where(t => t.Name.EndsWith("Repository"))
              .AsImplementedInterfaces();
        }
    }

7、程序启动注入

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //程序启动注入
            AutoFacBootStrapper.CoreAutoFacInit();
        }

8.接口调用数据

        public IPersonServices IServices { get; set; }
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            var list = IServices.GetAll();
            return new string[] { "value1", "value2" };
        }

9.运行访问api/values/,打个断点看下搞定

三、总结

autofac确实用起来很方便,上面只是简单的实现,如果想深入学习可以下载我上一个文章提供的两个开源的项目可以学习下,也可以到autofac官网去了解下。

最近在看相关文章,很多都太专业化了没怎么看懂,这是自己现在对IoC的一些理解,记录下来,要不然时间一久,也就忘了。

自己对IoC模式理解还很浅,希望得到各位的指点。

代码下载:

https://yunpan.cn/c6QCURhYmGcP9 (提取码:e97a)

AutoFac容器初步

 

转载请注明出处,AutoFac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

那么我们怎么来使用这样一个框架呢

1、在引用项右击,选择Nuget管理,这里我们要导入两个包

一个是AutoFac包,另外一个就是Autofac ASP.NET MVC5 Intergration

在webapi里面使用的话我们需要添加一个Autofac ASP.NET Web API2.2 Intergration 才可以。

2.Global.asax.cs属性注入,配置IOC容器,我这里配置的是通用的以I开头的Repository(仓库类)

#region autofac IOC容器配置
            var builder = new ContainerBuilder();

            //注册所有的controller
            builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
            //注册所有模块module
            builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());

            var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();

            //注册所有继承IDependency接口的类
            builder.RegisterAssemblyTypes(assemblys)
            .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);

            //注册服务,所有IxxxxRepository=>xxxxRepository
            builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();

            var container = builder.Build();

            BaseInfo._container = container;

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            #endregion

3.新建实体基类以及实体类,也就是创建数据模型

base类:

public class BaseEntity
    {
        [NotMapped]
        [PropertyModelBinder("start")]
        public int pageIndex { get; set; }

        [NotMapped]
        [PropertyModelBinder("length")]
        public int pageSize { get; set; }

        [NotMapped]
        public string draw { get; set; }

        [NotMapped]
        public List<Orderby> order { get; set; }

        [NotMapped]
        public List<Datacolumn> columns { get; set; }

    }

   public class Orderby {
       public string column { get; set; }

       public string dir { get; set; }
   }

   public class Datacolumn {
       public string data { get; set; }

       public string name { get; set; }

       public bool searchable { get; set; }

       public bool orderable { get; set; }
   }

实体类:

public class User : BaseEntity
    {
       public User() {
           RoleList = new List<Role>();
           MessageList = new List<UserMappingMessage>();
       }
       public int UserID { get; set; }

       public string UserName { get; set; }

       public string UserPassword {get;set;}

       public string UserReallyname {get;set;}

       public string HeadPortrait { get; set; }

       public string MobilePhone { get; set; }

       public string Email { get; set; }

       public int DepartmentID {get;set;}

       public bool IsEnable {get;set;}

       public DateTime CreateTime {get;set;}

       public DateTime? UpdateTime {get;set;}

       public string Remark { get; set; }

       public ICollection<Role> RoleList { get; set; }

       //接收消息列表
       public ICollection<UserMappingMessage> MessageList { get; set; }

       public Dictionary Department { get; set; }

       //发送消息列表
       public List<Message> Messages { get; set; }

    }

4.创建仓储接口,因为我在配置Global属性时,已经说明了我要注入所有以 “I” 开头的接口,那么我就把这个用户的接口给定义为IUserRepository

当然,不同的实体类所需要的仓储接口也不一样,这里根据自己的实际需求去写需要的方法类,接口嘛,就不要在这里具体实现你的方法了

 public interface IUserRepository
    {
        Tuple<int,List<User>> GetList(User model);

        List<User> GetUserInfos();

        User GetSingle(User model);

        User GetbyID(int userID);

        void AddUser(User model);

        void ModifyUser(User model);

        void DeleteUser(User model);

        void SetUserInfoRole(int userID, List<int> roleIDList);

        List<AutoUserDo> GetUserInfobyName(string value);

        void ResetUserPWDbyID(int id);

    }

5.我们定义一个实现接口的类,然后把接口的方法给实现,这里面就是对数据实体进行操作了

public class UserRepository : IUserRepository
    { 

        public Tuple<int, List<User>> GetList(User model)
        {
            using (UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>())
            {
                var SysUserRepository = dal.GetRepository<User>();

                var conditions = ExpandHelper.True<User>();
                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And(a => a.UserName.Contains(model.UserName));

                if (!string.IsNullOrEmpty(model.UserReallyname))
                    conditions = conditions.And(a => a.UserReallyname.Contains(model.UserReallyname));

                if (model.DepartmentID > 0)
                    conditions = conditions.And(a => a.DepartmentID == model.DepartmentID);

                var templist = SysUserRepository.Get(filter: conditions, includeProperties: "RoleList");

                var count = templist.Count();

                if (model.order != null&&model.order.Count()>0)
                {
                    foreach (var item in model.order)
                    {
                        var column = model.columns.ElementAt(int.Parse(item.column));
                        templist = templist.OrderSort(column.data, item.dir);
                    }

                }
                var result = templist.PageBy(model.pageIndex, model.pageSize).ToList();

                return new Tuple<int, List<User>>(count, result);
            }
        }

        public User GetSingle(User model)
        {
            using(UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>()){

                var conditions = ExpandHelper.True<User>();

                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And( a => a.UserName == model.UserName || a.MobilePhone == model.UserName);
                if (!string.IsNullOrEmpty(model.MobilePhone))
                    conditions = conditions.And(a => a.MobilePhone == model.MobilePhone);

                var result = dal.GetRepository<User>().Get(conditions).FirstOrDefault();
                return result;
            }
        }

        public User GetbyID(int userID)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

              //  var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID, includeProperties: "RoleList.MenuList,RoleList.rbList").AsNoTracking().FirstOrDefault();

                var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID,includeProperties: "RoleList").FirstOrDefault();

                foreach (var item in result.RoleList)
                {
                    var role=dal.GetRepository<Role>().Get(a=>a.RoleID==item.RoleID,includeProperties:"MenuList,rbList").FirstOrDefault();
                    item.MenuList = role.MenuList;
                    item.rbList = role.rbList;
                } 

                return result;
            }
        }

        public void AddUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                dal.GetRepository<User>().Insert(model);
                dal.Save();
            }
        }

        public void ModifyUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                dal.GetRepository<User>().UpdateSup(model, new List<string>() { "IsEnable", "CreateTime" }, false);
                dal.Save();
            }
        }

        public void DeleteUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
               var sysUserRepository= dal.GetRepository<User>();
               var Usermodel = sysUserRepository.GetByID(model.UserID);
               Usermodel.IsEnable=Usermodel.IsEnable?false:true;
               sysUserRepository.UpdateSup(Usermodel, new List<string>() { "IsEnable" });
               dal.Save();
            }
        }

        /// <summary>
        /// 添加用户角色信息,先删除原有数据,在添加到数据库
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="roleIDList"></param>
        /// <returns></returns>
        public void SetUserInfoRole(int userID, List<int> roleIDList)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                var sysUserRepository = dal.GetRepository<User>();
                var roleRepository = dal.GetRepository<Role>();
                var UserModel = GetbyID(userID);
                var roleList = UserModel.RoleList.ToList();

                roleList.ForEach(m =>
                {
                    var userModel = sysUserRepository.Get(filter: a => a.UserID == userID, includeProperties: "RoleList").FirstOrDefault();
                    var roleModel = roleRepository.GetByID(m.RoleID);
                    userModel.RoleList.Remove(roleModel);
                });

                roleIDList.ForEach(m =>
                {
                    var userModel = sysUserRepository.GetByID(userID);
                    var roleModel = roleRepository.GetByID(m);
                    userModel.RoleList.Add(roleModel);
                });

                dal.Save();
            }
        }

        public List<AutoUserDo> GetUserInfobyName(string value)
        {
            Mapper.Initialize(a =>
            {
                a.CreateMap<User, AutoUserDo>()
                 .ForMember(au => au.id, op => { op.MapFrom(user => user.UserID); })
                 .ForMember(au => au.text, op => { op.MapFrom(user => user.UserReallyname); })
                 .ForMember(au => au.department, op => { op.MapFrom(user => user.Department.DicValue); });
                a.CreateMap<Role, roleinfo>();
            });

            using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) {

                return dal.GetRepository<User>()
                          .Get(a => a.UserReallyname.Contains(value) || a.MobilePhone == value, includeProperties: "Department,Role").ProjectToQueryable<AutoUserDo>().ToList();

            }
        }

        public void ResetUserPWDbyID(int id)
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                var repository = dal.GetRepository<User>();
                var usermodel = new User()
                {
                    UserID = id,
                    UserPassword = "123456"
                };
                repository.UpdateSup(usermodel, new List<string>() { "UserPassword" });
                dal.Save();
            }
        }

        public List<User> GetUserInfos()
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                return dal.GetRepository<User>().Get().ToList();
            }
        }
    }

6.然后我们就可以在MVC的控制器里面去调用这些方法来实现我们所想要的功能了,我这里只展示一个方法

public void SendEmailAsync(Message model)
        {
            Task.Run(() =>
            {
                try
                {
                    var reclist = string.Empty;
                    foreach (var item in model.RecUser.Split(','))
                    {
                        var userinfo = this.UserRepository.GetbyID(int.Parse(item));  //这里就调用了实现接口的那个类的方法,去验证用户的ID
                        if (!string.IsNullOrEmpty(userinfo.Email))
                        {
                            reclist += userinfo.Email + ",";
                        }
                    }
                    if (!string.IsNullOrEmpty(reclist))
                    {
                        reclist = reclist.Substring(0, reclist.Length - 1);
                        EmailHelper email = new EmailHelper(reclist, model.MessageTitle, model.MessageText);
                        email.Send();
                    }
                    model.SendEmailState = 2;
                    this.MessageServer.SetSendState(model);
                }catch(Exception ex){
                    new LogHelper().LogError("发送邮件异常" + ex);
                    model.SendEmailState = 3;
                    this.MessageServer.SetSendState(model);
                }
            });
        }

那么整个流程就是这样,看着别人写的那些博客里面的流程不是那么的全面,我这里就详细的把AutoFac的整个流程给梳理出来了,有不对的地方请及时指出

后面我会详细说明一下Unity IOC框架是如何使用的,这里我就不再叙述了

下面是两篇比较好的博文,我觉得比较有参考意义的,可以看一下,喜欢我发布的内容的可以关注我,后面还会有其他的干货和内容进行分享

.NET领域最为流行的IOC框架之一Autofac:https://www.cnblogs.com/yinrq/p/5381492.html

.NET Unity IOC框架使用实例:https://blog.csdn.net/chen_peng7/article/details/54896449

.NET领域最为流行的IOC框架之一Autofac WebAPI2使用Autofac实现IOC属性注入完美解决方案 AutoFac容器初步的更多相关文章

  1. WebAPI2使用Autofac实现IOC属性注入完美解决方案

    一.前言 只要你是.NETer你一定IOC,IOC里面你也会一定知道Autofac,上次说了在MVC5实现属性注入,今天实现在WebApi2实现属性注入,顺便说一下autofac的程序集的注入方式,都 ...

  2. .NET领域最为流行的IOC框架之一Autofac

    一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也是用的Autofac. Orchad和Nopcomm ...

  3. Spring 中IOC(控制反转)&& 通过SET方式为属性注入值 && Spring表达式

    ### 1. Spring IoC IoC:Inversion of control:控制反转:在传统开发模式下,对象的创建过程和管理过程都是由开发者通过Java程序来实现的,操作权在开发者的Java ...

  4. Java框架spring 学习笔记(六):属性注入

    属性注入:创建对象的时候,向类里面的属性设置值. Java属性注入有三种方法: 使用set方法注入 有参数构造注入 使用接口注入 Spring框架里面的属性注入方式 有参数构造属性注入 set方法属性 ...

  5. IOC框架之一Autofac

    .NET领域最为流行的IOC框架之一Autofac 一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也 ...

  6. .Net IOC框架入门之三 Autofac

    一.简介   Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个 目的 1.依赖注入的目的是为了解耦. 2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置. 3.控制反转即 ...

  7. .Net IOC框架入门之——Autofac

    一.简介  Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个 目的 1.依赖注入的目的是为了解耦.2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置.3.控制反转即IoC ...

  8. IOC框架的认识

    转:http://blog.csdn.net/wanghao72214/article/details/3969594 1 IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实 ...

  9. 轻量级IOC框架:Ninject

    Ninject 学习杂记 - liucy 时间2014-03-08 00:26:00 博客园-所有随笔区原文  http://www.cnblogs.com/liucy1898/p/3587455.h ...

随机推荐

  1. Android Studio项目生成Jar包

    步骤: 1)在module的gradle文件中,将apply plugin:'com.android.application'改为apply plugin:'com.android.library' ...

  2. Mybatis之注解实现动态sql

    通过注解实现动态sql一共需要三部:1.创建表,2.创建entity类,3.创建mapper类, 4.创建动态sql的Provider类.1.和2.可以参见该系列其他文章,这里主要对3和4进行演示,并 ...

  3. Django初识 学习笔记一

    Django初识 学习笔记一 mvcviewsmodelstemplate. 一 MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(c ...

  4. asp.net core下的如何给网站做安全设置

    首先,我们来看下stack overflow网站的请求头文件: 可以看到一些我们熟悉或是陌生的HTTP头部文件字段.在这里我们在对HTTP输入流的头部文件中,做一些基本的防护.首先要明确,既然我们是对 ...

  5. PAT (Advanced Level) Practise 1004 解题报告

    GitHub markdownPDF 问题描述 解题思路 代码 提交记录 问题描述 Counting Leaves (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 1600 ...

  6. react那些事儿

    一.参考链接https://reactjs.org/http://react-china.org/https://doc.react-china.org/https://hulufei.gitbook ...

  7. Touch事件详解及区别,触屏滑动距离计算

    移动端有四个关于触摸的事件,分别是touchstart.touchmove.touchend.touchcancel(比较少用), 它们的触发顺序是touchstart-->touchmove- ...

  8. Navicat破解

    Navicat是一款我们经常使用的可视化sql工具,可偏偏它呢又收费,本着浪费可耻的理念,只有去网上找各种破解方法,却发现很多方法对于Navicat 12都不支持(本人使用的Navicat 12).最 ...

  9. 2004 ACM 成绩转换 两种方法

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2004 中文题目,简单题. 题意:将分数转换成ABC制 查表法 #include <stdio.h&g ...

  10. [蓝点zigBee] CC2530 实用教程总览

    Zstack 单个模块实验(无数据通信) 1Zstack精简,增加串口数据 Zstack 里面工程较多,整体代码量很大,若入门只需要先之关注其中的一个工程,在这个工程里添添补补逐步学习. 这一节主要是 ...