Ninject有多个绑定的情况下实现自动注入

下面这段代码,会报一个错误:

k.Bind<DALInterface>().To<SqlserverUserDAL>().Named("SqlServer");
k.Bind<DALInterface>().To<AccessUserDAL>().Named("Access");

var ord = k.Get<Order>();

"Error activating DALInterface More than one matching bindings are available. Matching bindings:  1) binding from DALInterface to SqlserverUserDAL  2) binding from DALInterface to AccessUserDAL Activation path:  2) Injection of dependency DALInterface into parameter _dal of constructor of type Order  1) Request for Order Suggestions:  1) Ensure that you have defined a binding for DALInterface only once.



这个错误提示表明在尝试激活 DALInterface 时,Ninject 找到了多个匹配的绑定(SqlserverUserDAL 和 AccessUserDAL),

这导致了冲突。根据提供的错误信息,这个问题发生在尝试构造 Order 类型的对象时,因为 Order 的构造函数依赖于 DALInterface

要解决这个问题,你需要确保在解析 Order 对象时明确指定使用哪个 DALInterface 的实现。

由于你已经使用了命名绑定,你可以在解析时通过指定绑定的名称来选择具体的实现。

// 首先获取你想要的DALInterface实现,这里以"SqlServer"为例  
var sqlDal = k.Get<DALInterface>("SqlServer");  
  
// 然后使用这个实现来构造Order对象  
var ord = new Order(sqlDal);  
ord.Insert();

我们首先解析名为 "SqlServer" 的 DALInterface 实现,然后使用这个实现来手动构造 Order 对象。

这样,Ninject 就不会在尝试自动注入 DALInterface 时产生冲突了。

另外,你还可以考虑重构你的代码或配置来避免这种冲突。

例如,你可以为每个实现创建不同的接口,这样你就可以在 Order 类中直接依赖于特定的接口,而不是通用的 DALInterface

或者,你可以使用条件绑定来确保在不同的上下文中使用不同的实现。


但是这样用不就不是自动注入了吗,怎么即有多组绑定,又可以自动注入?



这是一个常见的问题,即如何在有多个绑定的情况下实现自动注入。

通常,依赖注入框架(如 Ninject)在自动注入时会查找匹配的绑定,并且如果有多个匹配项,就会导致冲突。

在这种情况下,你可以使用一些技巧来解决问题并保留自动注入的功能。

上下文绑定(Contextual Binding)

你可以使用 Ninject 的上下文绑定功能来根据不同的上下文自动注入不同的实现。

这样,你可以定义多个绑定,但每个绑定只在特定的上下文中有效。

例如:


k.Bind<DALInterface>().To<SqlserverUserDAL>().WhenInjectedInto<Order>();
k.Bind<DALInterface>().To<AccessUserDAL>().WhenInjectedInto<SomeOtherClass>();

条件绑定(Conditional Binding)

除了上下文绑定,你还可以使用条件绑定,基于某些条件(如配置文件、环境变量等)选择不同的实现。

这样,Ninject 在解析依赖项时会根据条件选择合适的绑定。

例如:

k.Bind<DALInterface>().To<SqlserverUserDAL>().
    When(ctx => ConfigurationManager.AppSettings["UseSqlServer"] == "true");  
k.Bind<DALInterface>().To<AccessUserDAL>().
    When(ctx => ConfigurationManager.AppSettings["UseSqlServer"] != "true");

工厂模式(Factory Pattern)

另一种解决方案是使用工厂模式来创建对象。你可以定义一个工厂接口和相应的实现,让 Ninject 解析工厂接口,

然后在工厂实现中根据需要使用不同的 DALInterface 实现。

这样,你可以在运行时决定使用哪个实现,同时仍然利用 Ninject 的自动注入功能。

例如:

public interface IDALFactory  
{  
    DALInterface GetDAL();  
}  
  
public class DALFactory : IDALFactory  
{  
    private readonly IKernel _kernel;  
    public DALFactory(IKernel kernel) { _kernel = kernel; }  
    public DALInterface GetDAL() 
    { /* 根据需要使用 _kernel.Get<DALInterface>("...") 获取实现 */ }  
}


然后在你的 Order 类中:

public class Order  
{  
    private readonly IDALFactory _dalFactory;  
    public Order(IDALFactory dalFactory) { _dalFactory = dalFactory; }  
    public void Insert() 
    { /* 使用 _dalFactory.GetDAL() 获取需要的 DALInterface 实现 */ }  
}

总结

有多种方法可以在有多个绑定的情况下实现自动注入。

选择哪种方法取决于你的具体需求和项目结构。

上下文绑定和条件绑定是常用的技巧,而工厂模式则可以提供更灵活的对象创建方式。



下面的是构造函数方式的自动注入:


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

namespace IOC容器_Ninject
{
    class Program
    {
        static void Main(string[] args)
        {
            var k = new StandardKernel();   // 初始化Ninject的内核  
            k.Bind<DALInterface>().To<SqlserverUserDAL>();  // 绑定接口到具体的实现  
            var ord = k.Get<Order>();  // 获取Order对象,Ninject会自动注入其依赖项  
            ord.Insert();
            Console.ReadKey();
        }
    }

    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }


    //数据库读写
    public class SqlserverUserDAL : DALInterface
    {
        public void Insert(User user)
        {
            Console.WriteLine("SQL Server给User表插入一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("SQL Server根据ID得到User表一条记录");
            return null;
        }
    }

    public class AccessUserDAL : DALInterface
    {
        public void Insert(User user)
        {
            Console.WriteLine("Access给User表插入一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("Access根据ID得到User表一条记录");
            return null;
        }
    }

    public interface DALInterface
    {
        void Insert(User user);
        User GetUser(int id);
    }


    public class Order
    {
        private DALInterface dal;
        public Order(DALInterface _dal)
        {
            this.dal = _dal;
        }

        public void Insert()
        {
            dal.Insert(new User() { ID = 1, Name = "lxy1" });
        }

    
    }

}


下面是多个绑定下实现自动注入,使用上下文绑定:

        static void Main(string[] args)
        {
            var k = new StandardKernel();

            //k.Bind<DALInterface>().To<SqlserverUserDAL>();
            //k.Bind<DALInterface>().To<AccessUserDAL>();
            //上下文绑定
            k.Bind<DALInterface>().To<SqlserverUserDAL>().WhenInjectedInto<Order>();  
            var ord = k.Get<Order>();
            ord.Insert();
            Console.ReadKey();
        }


下面是多个绑定下实现自动注入,使用条件绑定:

        static void Main(string[] args)
        {
            var k = new StandardKernel();
            k.Bind<DALInterface>().To<SqlserverUserDAL>()
               .When(ctx => ConfigurationManager.AppSettings["UseSqlServer"] == "true"); 
            k.Bind<DALInterface>().To<AccessUserDAL>()
               .When(ctx => ConfigurationManager.AppSettings["UseAccessServer"] == "true");
            var ord = k.Get<Order>();
            ord.Insert();
            Console.ReadKey();
        }

配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="UseSqlServer" value="true" />
    <add key="UseAccessServer" value="false" />
    <!-- 其他设置 -->
  </appSettings>
</configuration>

注意:要使用 ConfigurationManager.AppSettings,你得先引入下面的命名空间:

image.png



下面是多个绑定下实现的自动注入,使用工厂模式:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ninject;
using Ninject.Parameters;
using System.Configuration;

namespace IOC容器_Ninject
{
    class Program
    {
        static void Main(string[] args)
        {
            var k = new StandardKernel();
            k.Bind<DALInterface>().To<SqlserverUserDAL>().Named(DALNameEnum.Sqlserver.ToString());
            k.Bind<DALInterface>().To<AccessUserDAL>().Named(DALNameEnum.Access.ToString());

            var ord = new Order(new DALFactory(k) { daltype= DALNameEnum.Sqlserver  });
            ord.Insert();
            Console.ReadKey();
        }
    }

    public interface IDALFactory
    {
        DALInterface GetDAL();
    }

    public enum DALNameEnum
    {
        Sqlserver,Access
    }

    public class DALFactory : IDALFactory
    {
        private readonly IKernel _kernel;
        public DALFactory(IKernel kernel) { _kernel = kernel; }

        public DALNameEnum daltype { get; set; }
        public DALInterface GetDAL()
        {
            DALInterface dal = _kernel.Get<DALInterface>(daltype.ToString()); ;
            return dal;
        }
    }

    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }


    //数据库读写
    public class SqlserverUserDAL : DALInterface
    {
        public void Insert(User user)
        {
            Console.WriteLine("SQL Server给User表插入一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("SQL Server根据ID得到User表一条记录");
            return null;
        }
    }

    public class AccessUserDAL : DALInterface
    {
        public void Insert(User user)
        {
            Console.WriteLine("Access给User表插入一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("Access根据ID得到User表一条记录");
            return null;
        }
    }

    public interface DALInterface
    {
        void Insert(User user);
        User GetUser(int id);
    }


    public class Order
    {
        private readonly IDALFactory _dalFactory;
        public Order(IDALFactory dalFactory)
        {
            _dalFactory = dalFactory;
        }

        public void Insert()
        {
            var dal = _dalFactory.GetDAL();
            dal.Insert(new User() { ID = 1, Name = "lxy1" });
        }
    }

}



其它参考资料:

下面是NInject的系列教程,请大家观看:

https://www.cnblogs.com/uncle_danny/p/6394887.html




--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2023-12-07 08:03:40 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864