我正在尝试使用this little library首次设置Ninject。 我有一个基本控制器,目前看起来像这样:
public class BaseController : ApiController
{
// Private properties
private IModelFactory factory;
// Public properties
public IServiceInterface Connection { get; private set; }
public IModelFactory Factory { get { return this.factory ?? (this.factory = new ModelFactory()); } }
/// <summary>
/// Default constructor
/// </summary>
public BaseController()
{
// Get our database settings
var setting = ConfigurationManager.AppSettings["Server"].ToUpper();
var type = (setting == "LIVE") ? ServiceInterface.ServerType.Azurerelay_live : ServiceInterface.ServerType.Azurerelay_test;
try
{
// Apply to our public properties
this.Connection = new ServiceInterface(type);
} catch
{
// Throw a 401 error
throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);
}
}
}
我想在这个构造函数上使用Ninject,但我似乎无法弄清楚如何执行 ServiceInterface ,因为它需要一个参数。 我试图像这样绑定服务:
// List and Describe Necessary HttpModules
// This class is optional if you already Have NinjectMvc
public class NinjectHttpModules
{
//Return Lists of Modules in the Application
public static NinjectModule[] Modules
{
get
{
return new[] { new MainModule() };
}
}
//Main Module For Application
public class MainModule : NinjectModule
{
public override void Load()
{
//TODO: Bind to Concrete Types Here
Kernel.Bind<IServiceInterface>().To<ServiceInterface>();
Kernel.Bind<IFactory>().To<Factory>();
}
}
}
并将我的构造函数更改为:
public class BaseController : ApiController
{
// Public properties
public readonly IServiceInterface Connection;
public readonly IModelFactory Factory;
/// <summary>
/// Default constructor
/// </summary>
public BaseController(IServiceInterface connection, IModelFactory factory)
{
try
{
// Apply to our public properties
this.Connection = connection;
this.Factory = factory;
} catch
{
// Throw a 401 error
throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);
}
}
}
但这不起作用,因为 ServiceInterface 需要一个参数来声明它是否存在。 有谁知道如何让这段代码起作用?
答案 0 :(得分:1)
防止在运行时从AppSettings
等地方读取配置值。不仅不需要多次读取它们(性能),而且在整个应用程序中分散它们的使用对可维护性和可靠性有深远的影响。而是将配置值的检索移动到应用程序的启动路径。这样:
您的Composition Root应该是这样的:
public override void Load()
{
var setting = ConfigurationManager.AppSettings["Server"].ToUpper();
var type = (setting == "LIVE")
? ServiceInterface.ServerType.Azurerelay_live
: ServiceInterface.ServerType.Azurerelay_test;
Kernel.Bind<IServiceInterface>().ToMethod(c => new ServiceInterface(type));
Kernel.Bind<IModelFactory>().ToMethod(c => new ModelFactory());
}
另一件事是你应该赞成composition over inheritance。基类是设计问题的标志。所以抛弃基类并将IModelFactory
和IServiceInterface
注入需要使用它们的具体类的构造函数中:
public class HomeController : ApiController
{
private readonly IModelFactory modelFactory;
private readonly IServiceInterface serviceInterface;
public HomeController(IModelFactory modelFactory, IServiceInterface serviceInterface)
{
this.modelFactory = modelFactory;
this.serviceInterface = serviceInterface;
}
// actions here
}
除了存储传入的依赖项之外,还要阻止在构造函数中执行任何操作。你injection constructors should be simple。这包括抛出异常等内容。防止从构造函数中抛出异常,因为这会产生resolving your object graph unreliable。
不要使用Service Locator anti-pattern,请确保组件只有one constructor,不要注入任何runtime data into them并注意constructor over-injection,因为这表示违反了Single Responsibility Principle。