我正在编写一个新的.NET库供我公司内部使用,它将通过依赖注入使用IoC.当然,如果我们使用IoC容器来解析实例,这个库将更容易使用.
但是,将调用此库的代码当前不使用任何类型的依赖注入,并且重构遗留代码以使用DI超出了我的项目的范围.那么,在这个遗留代码中开始使用Container从我的新库中获取实例的最佳方法是什么?
如果可能的话,我想避免乱丢遗留代码,硬编辑我选择的任何IoC容器.由于我对DI比较陌生,所以我们有可能会改变我们想要在某个时刻使用哪个Container的想法.
如果我将我的容器包装在CodePlex上的CommonServiceLocator库之类的东西上,这是一种合理的方法吗?
其他人做了什么?
我个人喜欢从C#代码配置StructureMap的选项.根据我的理解,DI的优点之一是我们可以轻松交换新的具体实例.但是,如果配置是在代码中定义的,那么具体实例在dll中是硬编码的.
所以,实际上,它与硬件编码依赖关系一样好,对吧?我知道,在测试过程中它会让生活更轻松......
我的观点是,使用xml配置不是更好吗?你想插入一个新的具体实例?只需让安装程序用新的文件覆盖structuremap.config文件.
那么,配置StructureMap的首选方法是什么?
额外:我暂时被迫使用C#配置,因为我不知道如何将连接字符串传递给实例.我可以在配置文件中编写连接字符串,但我想重用app.config中定义的连接字符串.
我有一个类,它具有我与Ninject连接的依赖项.
public interface IFoo {}
public class MyObject {
[Inject]
IFoo myfoo;
}
Run Code Online (Sandbox Code Playgroud)
在真正的实现中,我正在使用属性注入,但为了快速说明,我将注入该字段.据我所知,我需要使用,而不是新建MyObject实例,以便正确地注入依赖项
kernel.Get<MyObject>()
Run Code Online (Sandbox Code Playgroud)
然而,我磕磕绊绊的是MyObject只会在类库的上下文中使用.目的是让最终应用程序创建自己的模块并将其传递给内核实例以进行水合.鉴于此,通常最实用的方法是将Ninject内核的通用实例呈现给我的类库,以便MyObject(和其他类似情况)的实例可以被水合?
我的第一个倾向是某种工厂内部化单例内核 - 应用程序本身必须通过加载模块来进行水合/初始化.
所以在RandomService.cs中
var myKernel = NinjaFactory.Unleash();
var myobj = myKernel.Get<MyObject>();
myobj.foo();
Run Code Online (Sandbox Code Playgroud)
在我走这条路之前,我需要做一个完整性检查,以确保思路健全,或者没有其他一些我不知道的东西.我显然是IoC的新手,感觉我喜欢基础知识,但不一定是最好的现实世界使用方式.
我通常只是为自己做一个应用程序的业余爱好.看起来DI框架在社区中有很大的发展势头,所以我想也许我应该学习它以提高我的编码技能.据我了解,它似乎更倾向于大项目.在5k线项目中使用它仍然是一个好主意吗?
我在这里看到了关于这个论点的各种其他问题,最值得注意的是
Ioc/DI - 为什么我必须在输入应用程序中引用所有层/组件?
和这篇文章(和其他各种材料).
但是,我不清楚将组合根放在库(DLL).NET项目中的哪个位置.该项目不属于本文中提到的任何特定类型.在桌面,控制台甚至Web应用程序中,这一点都是明确定义的.
我目前的方法是包装容器,寄存器类型并重新公开Resolve方法:
class DefaultBootstrapper : IBootstrapper {
public Bootstrapper() {
_container = new XXXContainer();
RegisterTypes(_container);
}
public T Resolve<T>() where T : class {
return _container.Resolve<T>();
}
// + other _container.Resolve() overloads
private readonly XXXContainer _container;
}
Run Code Online (Sandbox Code Playgroud)
然后我阻止库消费者创建库的根实例(例如,定义内部构造函数),从而强制使用单例工厂:
class XYZFactory {
static XYZFactory() {}
private XYZFactory(IBootstrapper bootstrapper) {
_bootstrapper = bootstrapper;
}
public static XYZFactory Instance {
get { return Singleton; }
}
public ABCType CreateABCType(string param1) {
return _bootstrapper.Resolve<ABCType>(param1, …Run Code Online (Sandbox Code Playgroud) 我相信这些问题已经以某种方式或其他方式提出,但我还没有得到它.
我们做了一个GWT项目,我的项目负责人不允许使用GIN/Guice作为DI框架(新的程序员不会理解它,他认为)所以我尝试手动执行DI.
现在我遇到了深度对象图的问题.UI中的对象层次结构如下所示:
AppPresenter-> DashboardPresenter-> GadgetPresenter-> GadgetConfigPresenter
对象层次结构树中的GadgetConfigPresenter方式有一些依赖项,如CustomerRepository,ProjectRepository,MandatorRepository等.
因此,创建GadgetConfigPresenter的GadgetPresenter也具有这些依赖关系,依此类推,直到创建AppPresenter的应用程序的入口点.
在构建足够复杂的类库以使用内部依赖注入时,我应该注意什么?
假设它将使用Castle Windsor(作为示例),配置容器的最佳位置/方法是什么,假设该库将由简单的控制台应用程序(没有DI)使用,Web表单使用相同的容器( Castle Windsor)和使用不同容器(NInject)的网络应用程序?
我希望彼得或鲁本看到这个问题,因为他们似乎是关于Ninject的人.我需要创建一个自定义提供程序,因为我有一个需要4个参数的类.可以注入两个,因为它们是类型,但另外两个是配置参数并且是整数.它们以毫秒为单位引用超时.
[SingleInstance]
MyClass
{
ISomething something;
IOther other;
int timeout;
int delay;
[Inject]
MyClass(ISomething something, IOther other, int timeout, int delay)
{
this.something = something;
this.other = other;
this.timeout = timeout;
this.delay = delay;
}
}
Run Code Online (Sandbox Code Playgroud)
我以前依赖于我创建的工厂来获取超时和延迟的配置设置以及注入其他内容.现在它似乎正确,我将不得不创建自己的自定义提供程序.哪个我没关系.
几点加分:
所以,我最后的问题:
更新:代码样本按要求
然后,我认为我的提供者想要这样的东西:
class MyClassProvider : SimpleProvider<MyClass> {
protected override MyClass CreateInstance(IContext context) {
int timeout= ConfigurationManager.AppSettings.Get("timeout");
int delay= ConfiguraionManager.AppSettings.Get("delay");
ISomething something = new SomethingImpl();
IOther other = new OtherImpl();
MyClass newOne = New MyClass(something, other, timeout, delay); …Run Code Online (Sandbox Code Playgroud) 我有一个课程需要使用策略设计模式.在运行时,我需要切换不同的算法,以查看对应用程序性能的影响.
有问题的类目前在构造函数中有四个参数,每个参数代表一个算法.
如何使用Ninject(或通用方法)仍然可以使用IOC但使用策略模式?
目前的限制是我的内核(容器)知道每个算法接口,但只能绑定到一个具体的类.我现在可以看到的唯一方法是在构造中传递所有八种算法,但是使用不同的接口,但这似乎完全是不必要的.如果我没有使用IOC容器,我不会这样做,所以必须有一些解决方法.
代码示例:
class MyModule : NinjectModule
{
public override void Load()
{
Bind<Person>().ToSelf();
Bind<IAlgorithm>().To<TestAlgorithm>();
Bind<IAlgorithm>().To<ProductionAlgorithm>();
}
}
Run Code Online (Sandbox Code Playgroud)
人需要使用这两种算法,以便我可以在运行时切换.但只有TestAlgorithm被绑定,因为它是容器中的第一个.
我正在使用DI和IoC开发可扩展框架.用户必须能够通过将自己的实现放入容器中来覆盖框架内的现有功能.
如何让用户在不要求他们知道我正在使用哪个IoC容器的情况下执行此操作?
我目前的中途解决方案是按如下方式构建我的程序集:
1)定义仅包含接口的抽象程序集.
2)定义实现这些接口的具体组件.用户可以定义自己的内容以覆盖现有功能.
3)在单独的程序集中定义容器绑定; 即每个混凝土组件一个装订组件.
这意味着混凝土组件不与特定的IoC容器耦合,如果我使用不同的容器,它们将被关闭以防止更改.但是,用户仍然需要知道我的框架正在使用哪个容器来编写绑定程序集,如果我更改了IoC容器(即从Ninject到Spring),他们需要释放新的绑定程序集.
我错过了什么吗?
c# dependency-injection ninject ioc-container dependency-management