下面这段代码,会报一个错误:
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,你得先引入下面的命名空间:
下面是多个绑定下实现的自动注入,使用工厂模式:
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
版权声明:本文为博主原创文章,转载请附上博文链接!

