.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. POJ 3140 Contestants Division 【树形DP】

    <题目链接> 题目大意:给你一棵树,让你找一条边,使得该边的两个端点所对应的两颗子树权值和相差最小,求最小的权值差. 解题分析: 比较基础的树形DP. #include <cstdi ...

  2. JS的异步世界

    前言 JS的异步由来已久,各种异步概念也早早堆在开发者面前.可现实代码中,仍然充斥了各种因异步顺序处理不当的bug,或因不好好思考,或因不了解真相.今天,就特来再次好好探索一番JS的异步世界. 01 ...

  3. html5手势操作与多指操作封装与Canvas图片裁切实战

    当前情况,移动端的开发占比越来越高,单指的拖拽触碰等操作是常规需要.特殊的多指操作与手势操作还需另做处理,而且还涉及到兼容性问题. // 屏幕上存在两根或两根以上的手指 时触发 仅IOS存在手势事件, ...

  4. spring之基础知识总结

    spring是轻量级的(非侵入式,不用继承spring中的父类等).Spring框架主要提供了IoC容器.AOP.数据访问.Web开发.消息.测试等相关技术.本文主要介绍Spring中的一些小知识点, ...

  5. visual studio 加入zen-codding

    大家都知道zen codding的强大之处大家都知道了,那如何让visual studio也支持呢,直接下载插件安装即可: 插件下载地址:zen-codding for visual studio下载 ...

  6. UVA 220 Othello

    题意:输入n,代表次数,每次输入8*8的棋盘,处理3种命令:①L:打印所有合法操作,②M:放棋子,③Q:打印棋盘然后退出. 思路:①用字符数组存棋盘,整型数组存合法位置. ②查找的方法:当前玩家为cu ...

  7. JAVA实现Word(doc)文件读写

    1.pom.xml依赖 <dependencies> <dependency> <groupId>org.apache.poi</groupId> &l ...

  8. nodejs 支付宝app支付

    [链接]单笔转账到支付宝账户产品介绍更新时间:https://docs.open.alipay.com/309 const crypto = require('crypto') const momen ...

  9. java多态的向上转型与向下转型(与编译时类型与运行时类型有关)

    1.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 当编译时类型和运行时类型不一致时,就会出现所谓的多态. 因为子类是一个特殊的父类,因此java允许把一个子类对象直接 ...

  10. BZOJ3457 : Ring

    根据Polya定理: \[ans=\frac{\sum_{d|n}\varphi(d)cal(\frac{n}{d})}{n}\] 其中$cal(n)$表示长度为$n$的无限循环后包含$S$的串的数量 ...