我有一个基于ASP.NET MVC 5的应用程序。我正在尝试使用Unity.Mvc容器来帮助我进行依赖注入。
我有以下DbContext
类
public class MainContext : DbContext
{
public DbSet<User> Users { get; set; }
// .....
public MainContext(string connectionName)
: base(connectionName)
{
Database.SetInitializer<MainContext>(null);
}
}
构建MainContext
类时我想要使用的生产值是DefaultConnection
。我想将MainContext
类注册到容器中,并告诉Unity在使用解析时向构造函数提供DefaultConnection
字符串。
我尝试了以下
container.RegisterType<MainContext>("DefaultConnection", new PerRequestLifetimeManager(), new InjectionConstructor(new ResolvedParameter<string>("DefaultConnection")));
也尝试了这个
container.RegisterType<MainContext>("DefaultConnection", new PerRequestLifetimeManager(), new InjectionConstructor("DefaultConnection"));
但我一直收到以下错误
Resolution of the dependency failed, type = 'System.Web.Mvc.IController', name = 'MyProject.Controllers.HomeController'.
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.
-----------------------------------------------
At the time of the exception, the container was:
Resolving MyProject.Controllers.HomeController, MyProject.Controllers.HomeController (mapped from System.Web.Mvc.IController, MyProject.Controllers.HomeController)
Resolving parameter 'unitOfWork' of constructor MyProject.Controllers.HomeController(MyProject.Repositories.Contracts.IUnitOfWork unitOfWork)
Resolving MyProject.Repositories.UnitOfWork,(none) (mapped from MyProject.Repositories.Contracts.UnitsOfWork.IUnitOfWork, (none))
Resolving parameter 'context' of constructor MyProject.Repositories.UnitOfWork(MyProject.Contexts.MainContext context)
Resolving MyProject.Contexts.MainContext,(none)
Resolving parameter 'connectionName' of constructor MyProject.Contexts.MainContext(System.String connectionName)
Resolving System.String,(none)
解决方法是将我的MainContext
课程更改为此
public class MainContext : DbContext
{
public DbSet<User> Users { get; set; }
// .....
public MainContext(string connectionName)
: base(connectionName)
{
Database.SetInitializer<MainContext>(null);
}
public MainContext(string connectionName)
: this("DefaultConnection")
{
}
}
然后像我这样注册我的课程
container.RegisterType<MainContext>(new PerRequestLifetimeManager(), new InjectionConstructor());
但是,我不想将我的实现与特定的连接名称结合起来。我希望IoC为MainContext
提供连接名称。换句话说,我希望能够在不更改MainContext
类的情况下交换连接名称。
如何正确地告诉Unity-Container注册MainContext
类并在构造时使用DefaultConnection
?
答案 0 :(得分:1)
这不能直接回答我的问题,但给了我一个灵活的解决方法。
我创建了以下界面
public interface IDatabaseConnection
{
string NameOrConnectionString { get; }
}
然后我创建了这个类的以下实现
public class DefaultDatabaseConnection: IDatabaseConnection
{
public string Name { get; private set; }
public DefaultDatabaseConnection()
{
NameOrConnectionString = "DefaultConnection";
}
public DefaultDatabaseConnection(string connectionName)
{
NameOrConnectionString = connectionName;
}
}
然后我将MainContext
课程改为此
public class MainContext : DbContext
{
public DbSet<User> Users { get; set; }
// .....
public MainContext(IDatabaseConnection connection)
: base(connection.NameOrConnectionString)
{
Database.SetInitializer<MainContext>(null);
}
}
最后,我注册了我的课程
container.RegisterType<IDatabaseConnection, DefaultDatabaseConnection>("DefaultDatabaseConnection", new InjectionConstructor());
container.RegisterType<MainCompanyContext>(new PerRequestLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDatabaseConnection>("DefaultDatabaseConnection")));
如果有更好的答案,我会接受其他答案,所以如果有更简单的方法或者有办法为InjectionConstructor
班级提供原始字符串,请引导我。
答案 1 :(得分:0)
静态值
如果要对要传递给构造函数的字符串进行硬编码,只需执行以下操作:
container.RegisterType<IMyInterface, MyClass>(
new InjectionConstructor(
"ThisIsAHardCopedString",
new ResolvedParameter<IOtherInput>()));
参数化值
但是,例如,如果要使用配置文件中的string
,则可以执行以下操作:
container.RegisterType<IMyInterface, MyClass>(
new InjectionConstructor(
new ResolvedParameter<string>("TheNameOfMyString"),
new ResolvedParameter<IOtherInput>()));
在您的主项目中,您注册了字符串:
container.RegisterInstance<string>("TheNameOfMyString", Settings.Default.ParameterName);
看起来你想要解决方案1,但我建议使用解决方案2,以便将来更容易更改。
注意:您可以让LifetimeManagers
与解决方案共存,但这与解决方案无关。