策略模式和依赖注入都允许我们在运行时设置/注入对象.策略模式和依赖注入之间有什么区别?
我正在启动一个新的桌面应用程序,我想使用MVVM和WPF构建它.
我也打算使用TDD.
问题是我不知道如何使用IoC容器将依赖项注入我的生产代码.
假设我有以下类和接口:
public interface IStorage
{
bool SaveFile(string content);
}
public class Storage : IStorage
{
public bool SaveFile(string content){
// Saves the file using StreamWriter
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有另一个IStorage作为依赖项的类,假设这个类是一个ViewModel或一个业务类......
public class SomeViewModel
{
private IStorage _storage;
public SomeViewModel(IStorage storage){
_storage = storage;
}
}
Run Code Online (Sandbox Code Playgroud)
有了这个,我可以轻松编写单元测试,以确保它们正常工作,使用模拟等.
问题是在实际应用中使用它.我知道我必须有一个链接IStorage接口默认实现的IoC容器,但我该怎么做呢?
例如,如果我有以下xaml会怎么样:
<Window
... xmlns definitions ...
>
<Window.DataContext>
<local:SomeViewModel />
</Window.DataContext>
</Window>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如何正确地"告诉"WPF注入依赖项?
另外,假设我需要一个SomeViewModel来自我的cs代码的实例,我应该怎么做?
我觉得我完全迷失了,我会感谢任何有关如何处理它的最好方法的例子或指导.
我熟悉StructureMap,但我不是专家.此外,如果有更好/更容易/开箱即用的框架,请告诉我.
提前致谢.
我在一些帖子中读过,Spring MVC并Portlets建议不要进行现场注射.因为我试图得到一个所以我问自己我是否使用现场注射,我无法回答它.据我所知场注入是,如果你注入一个Bean与一个属性@Autowired是这样的:
CartController.java:
...
@Autowired
private Cart cart;
...
Run Code Online (Sandbox Code Playgroud)
BookshopConfiguartion.java:
@Configuration
public class BookShopConfiguration {
@Bean
public Cart cart(){
return new Cart();
}
//more configuration
Run Code Online (Sandbox Code Playgroud)
我Cart.java习惯于在购物车中存储和提供有关书籍的信息.
在我的研究期间,我读到了构造函数注入:
MyComponent.java:
...
public class MyComponent{
private Cart cart;
@Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
...
Run Code Online (Sandbox Code Playgroud)
这两种注射的优点和缺点是什么?
编辑1:由于此问题被标记为此问题的重复,我检查了它.因为在问题和答案中都没有任何代码示例,我不清楚我是否正确猜测我正在使用哪种注射类型.
有没有办法为已经引导的角度模块注入延迟依赖?这就是我的意思:
假设我有一个站点范围的角度应用程序,定义为:
// in app.js
var App = angular.module("App", []);
Run Code Online (Sandbox Code Playgroud)
在每一页:
<html ng-app="App">
Run Code Online (Sandbox Code Playgroud)
稍后,我重新打开应用程序,根据当前页面的需要添加逻辑:
// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
Run Code Online (Sandbox Code Playgroud)
现在,说是逻辑的那些点播位中的一个还需要自己的依赖关系(如ngTouch,ngAnimate,ngResource,等).如何将它们附加到基础应用程序?这似乎不起作用:
// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped
Run Code Online (Sandbox Code Playgroud)
我意识到我可以事先做好一切,即 -
// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);
Run Code Online (Sandbox Code Playgroud)
或者自己定义每个模块,然后将所有内容注入主应用程序(有关更多信息,请参阅此处):
// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', …Run Code Online (Sandbox Code Playgroud) 我使用Microsoft的Unity进行依赖注入,我想做这样的事情:
IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context
IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);
Run Code Online (Sandbox Code Playgroud)
RepositoryA并且RepositoryB都有一个带IDataContext参数的构造函数,我希望Unity使用我传递它的上下文初始化存储库.另请注意,IDataContext未在Unity中注册(我不想要3个实例IDataContext).
.net c# dependency-injection unity-container constructor-injection
当被问及Scala中的依赖注入时,很多答案都指向使用Reader Monad,无论是来自Scalaz还是只是自己编写.有很多非常明确的文章描述了这种方法的基础知识(例如,Runar的演讲,Jason的博客),但我没有设法找到更完整的例子,我没有看到这种方法的优势超过例如更多传统的"手动"DI(参见我写的指南).最有可能的是我错过了一些重要的观点,因此问题就出现了.
举个例子,我们假设我们有这些类:
trait Datastore { def runQuery(query: String): List[String] }
trait EmailServer { def sendEmail(to: String, content: String): Unit }
class FindUsers(datastore: Datastore) {
def inactive(): Unit = ()
}
class UserReminder(findUser: FindUsers, emailServer: EmailServer) {
def emailInactive(): Unit = ()
}
class CustomerRelations(userReminder: UserReminder) {
def retainUsers(): Unit = {}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我使用类和构造函数参数进行建模,这与"传统"DI方法非常相似,但是这个设计有几个好的方面:
UserReminder不知道FindUsers需要数据存储.功能甚至可以在单独的编译单元中IO如果我们想要捕获效果等,"业务逻辑"方法可以返回包含在monad中的值.怎么能用Reader monad建模呢?保留上面的特性会很好,因此很清楚每个功能需要什么样的依赖关系,并隐藏一个功能与另一个功能的依赖关系.请注意,使用classes更多的是实现细节; 也许使用Reader monad的"正确"解决方案会使用其他东西.
我找到了一个有点相关的问题,暗示:
假设我有一个模块:
Module extends AbstractModule
{
@Override
protected void configure()
{
bind(String.class).
annotatedWith(Names.named("annotation")).
toInstance("DELIRIOUS");
}
}
Run Code Online (Sandbox Code Playgroud)
我想测试模块并检查它是否在没有类和String字段的注释字段中注入正确的值Names.named("annotation")但是直接从注入器获取值:
@Test
public void test()
{
Injector injector = Guice.createInjector(new Module());
// THIS IS NOT GOING TO WORK!
String delirious = injector.getInstance(String.class);
assertThat(delirious, IsEqual.equalTo("DELIRIOUS");
}
Run Code Online (Sandbox Code Playgroud) 我有一个父组件进入服务器并获取一个对象.
// parent component
@Component({
selector : 'node-display',
template : `
<router-outlet [node]="node"></router-outlet>
`
})
export class NodeDisplayComponent implements OnInit {
node: Node;
ngOnInit(): void {
this.nodeService.getNode(path)
.subscribe(
node => {
this.node = node;
},
err => {
console.log(err);
}
);
}
Run Code Online (Sandbox Code Playgroud)
在(孩子中的一个)我的孩子展示
export class ChildDisplay implements OnInit{
@Input()
node: Node;
ngOnInit(): void {
console.log(this.node);
}
}
Run Code Online (Sandbox Code Playgroud)
看起来我没想到只能将数据注入路由器插座.看起来我在Web控制台中收到了错误...
Can't bind to 'node' since it isn't a known property of 'router-outlet'.
Run Code Online (Sandbox Code Playgroud)
这有点道理,但我怎么做以下......
// parent component
@Component({
selector : 'node-display',
template : …Run Code Online (Sandbox Code Playgroud) 我试图找出log4net与依赖注入框架的正确模式和用法.
Log4Net使用ILog接口但需要我调用
LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)
Run Code Online (Sandbox Code Playgroud)
在我需要记录信息的每个类或方法中.这似乎违背了IoC原则并让我使用Log4Net.
我应该以某种方式在某处放置另一层抽象?
此外,我需要记录自定义属性,如当前用户名,如下所示:
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
Run Code Online (Sandbox Code Playgroud)
我如何封装它,以便我不必记住每次都这样做并仍然保持当前记录的方法.我应该做这样的事情还是我完全错过了标记?
public static class Logger
{
public static void LogException(Type declaringType, string message, Exception ex)
{
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
ILog log = LogManager.GetLogger(declaringType);
log.Error(message, ex);
}
}
Run Code Online (Sandbox Code Playgroud) 这是设置.假设我有一些需要服务实例的动作过滤器:
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething(){}
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个需要该服务实例的ActionFilter:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService; // <--- How do we get this injected
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
在MVC 1/2中,将依赖关系注入动作过滤器是一个痛苦的屁股.最常见的方法是使用自定义操作调用因为在这里可以看到:http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/的这种解决方法背后的主要动机是因为以下方法被认为是与容器的草率和紧密耦合:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService;
public MyActionFilter()
:this(MyStaticKernel.Get<IMyService>()) //using Ninject, but would apply to any container
{
}
public MyActionFilter(IMyService myService)
{
_myService = myService;
} …Run Code Online (Sandbox Code Playgroud) c# asp.net-mvc dependency-injection actionfilterattribute asp.net-mvc-3
c# ×3
java ×2
.net ×1
angular ×1
angularjs ×1
annotations ×1
asp.net-mvc ×1
autowired ×1
dependencies ×1
guice ×1
log4net ×1
mvvm ×1
portlet ×1
scala ×1
scalaz ×1
spring-mvc ×1
wpf ×1