see*_*_87 7 c# dependency-injection asp.net-mvc-3
所以这就是问题,我的mvc3项目使用依赖注入,并有一个基本的通用IRepository类,其他存储库派生自此类.
所以我可以提前做并在控制器中执行此操作:
public class SomethingController
{
IOrderRepository repository;
public SomethingController(IOrderRepository repo)
{
this.repository = repo;
}
public ActionResult SaveOrder(Order order)
{
repository.add(order)
unitOfWork.CommitChanges(); // THIS works!
}
}
Run Code Online (Sandbox Code Playgroud)
但现在我需要在这样的自定义静态非控制器中使用其中一个存储库:
static class OrderParser
{
private IOrderRepository repo;
public static DoWork()
{
repo = DependencyResolver.Current.GetService<IOrderRepository>();
var ordersInDB = repo.GetAllOrders(); //THIS works!
//But!
var ordersForInsertion = new List<Order>();
//do some backgroundworker magic
//fetch txt files from an ftp server
var ordersForInsertion = ParseTextFilesIntoOrders();
foreach order in ordersForInsertion
repo.add(order)
unitOfWork.CommitChanges();
// THIS doesnt commit anything into the database
// It also doesnt throw any exceptions
// and repo isnt null or any of that
}
}
Run Code Online (Sandbox Code Playgroud)
所以,作为测试,我尝试过:
repo = DependencyResolver.Current.GetService<IOrderRepository>();
Run Code Online (Sandbox Code Playgroud)
在第一个例子中的控制器类内部,看它是否也没有提交东西,并且它没有.(以正确的方式执行[通过构造函数注入存储库和unitOfWork]工作!)
所以它必须与DependencyResolver有关,对吧?
注意:如果还有更多的代码需要我发布,请立即离开,我会在这里快速编辑它!
注2:Thanx!
EDIT1:
关于w0lf的超快速答案以下是一些更多信息:
我的OrderParser类包含一个backgroundWorker,它应该是:
所有这一切都必须在没有任何用户操作的情况下发生,这意味着该操作不是来自控制器,因此我所做的就是:
在我的bootstrapper类中
Initialise()
{
//Unrelated stuff
OrderParser.DoWork()
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么我将它作为静态类实现(很容易变为非静态)
EDIT2:
它会是这样的:
class OrderParser
{
private IOrderRepository repo;
public OrderParser(IOrderRepository foo)
{
this.repo = foo;
}
public static DoWork()
{
//use repo var!
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我在bootstrapper Initialize()方法中实例化时,我该怎么做,例如:
class bootstrapper
{
Initialize()
{
var parser = new OrderParser(/*how do i pass the dependency here?*/)
parser.DoWork();
}
}
Run Code Online (Sandbox Code Playgroud)
EDIT3:
这里有一些更多的测试,请耐心等待!
这是我的OrderParser:
class OrderParser
{
public OrderParser(IOrderRepository foo, IContext unitOfWork)
{
foo.getall();
foo.add(some_order);
unitOfWork.commit();
}
}
Run Code Online (Sandbox Code Playgroud)
public class SomeController
{
IOrderRepository repository;
public SomeController(IOrderRepository repo)
{
this.repository = repo;
}
public ActionResult SomeMethod(Order order)
{
repository.GetAll(); //WORKS
repository.add(order)
unitOfWork.CommitChanges(); // WORKS
}
}
Run Code Online (Sandbox Code Playgroud)
class bootstrapper
{
Initialize()
{
//Build unity container..
//set resolver..
var parser = new OrderParser(container.Resolve<IOrderRepository>, container.Resolve<IContext>)
//can getAll, cant commit.
}
}
Run Code Online (Sandbox Code Playgroud)
public class SomeController
{
IOrderRepository controllers_repository;
public SomeController(IOrderRepository repo)
{
this.controllers_repository = repo;
}
public ActionResult SomeMethod(Order order)
{
var parser = new OrderParser(DependencyResolver.Current.GetService<IOrderRepository>,
DependencyResolver.Current.GetService<IContext>)
//can do getall, no commits
var parser = new OrderParser(controllers_repository, controllers_icontext)
// obviously works (can getall and commit)
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,当我说"不能提交"时,它不是我得到一个例外或者存储库是null,nope.代码运行好像没关系,只有DB不会改变.
一种可能的解决方案是使OrderParser
类非静态,并在Controller的构造函数中注入它的一个实例,以触发action(DoWork
).
然后make OrderParser
的构造函数接受IOrderRepository参数,IoC容器很乐意处理它.
另外,要注意以下事项:
DependencyResolver.Current.GetService<ISomeInterface>();
Run Code Online (Sandbox Code Playgroud)
这称为服务定位器,它被认为是反模式.尽可能避免使用它.
基本上,您应该参考的唯一地方DependencyResolver.Current.GetService
是您的实现,IControllerFactory
它首先启用DI.
更新:
如果你在另一个应用程序中执行此操作最好,而不是MVC网站.两种选择是:
这些是独立的应用程序将有自己的组合根,可以处理对象实例化/依赖注入问题.
但是,如果您不得不通过Web应用程序执行此操作(例如 - 您拥有仅允许Web应用程序的托管),那么您可能会发现"不要直接使用Dependencey Resolver"的例外情况可以接受"在应用程序启动时规则并做这样的事情:
var runner = DependencyResolver.Current.GetService<OrderParsingRunner>();
runner.StartWorking();
Run Code Online (Sandbox Code Playgroud)
当然,这个OrderParsingRunner
类看起来像这样:
public class OrderParsingRunner
{
private readonly OrderParser orderParser;
public OrderParsingRunner(OrderParser orderParser)
{
this.orderParser = orderParser;
}
public StartWorking()
{
TaskFactory.StartNew(() =>
{
DoWorkHourly();
});
}
private DoWorkHourly()
{
while(true)
{
Thread.Sleep(TimeSpan.FromHours(1));
orderParser.DoWork();
}
}
}
Run Code Online (Sandbox Code Playgroud)
免责声明:我实际上没有编译/运行这段代码,我只是写它来说明这个概念.
请注意,这是一种解决方法,而不是实际的解决方案.如果可能,建议您使用其他应用程序执行后台任务.