我正在尝试使用StructureMap附带的MoqAutoMocker类,但我找不到任何应该如何使用它的示例.我必须继续使用的是使用RhinoMocks的StructureMap站点的示例.
我要做的是使用Get方法引用我的一个自动模拟/注入依赖项.根据上面的链接,我应该可以做这样的事情
// This retrieves the mock object for IMockedService
autoMocker.Get<IMockedService>().AssertWasCalled(s => s.Go());
Run Code Online (Sandbox Code Playgroud)
注意如何使用AssertWasCalled,这表明Get函数返回对RhinoMocks Mock对象的引用?当我使用MoqAutoMocker时,同样的代码对我不起作用.
我有一个类SignInController,它依赖于构造函数中的ISecurityService.在示例中使用了像RhinoAutoMocker这样的MoqAutoMocker,我想我应该能够做到这一点......
var autoMocker = new MoqAutoMocker<SignInController>();
autoMocker.Get<ISecurityService>().Setup(ss => ss.ValidateLogin
(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
Run Code Online (Sandbox Code Playgroud)
但问题是我永远无法访问Setup方法.在这种情况下,对autoMocker.Get的调用似乎返回了一个ISecurityService实例而不是Mock <ISecurityService>
有没有人以这种方式成功使用过MoqAutoMocker?我只是做错了吗?
以下哪种语法被认为是最佳实践?
For<IMyInterface>().LifecycleIs(new HybridLifecycle()).Use<MyImplementation>();
For<IMyInterface>().LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.Hybrid)).Use<MyImplementation>();
Run Code Online (Sandbox Code Playgroud)
如果第一个是正确的,我可以创建一个对象HybridLifecycle,并将其用于多个For <...>语句,还是每个For <>都需要创建一个新的HybridLifecycle?
我对像StructureMap这样的DI容器有点新,我用asp.net mvc应用程序已经用了很短的时间.现在,我正在拆分我的架构,它将拥有一个WCF服务层和一些消费者,如ASP.NET MVC应用程序,Silverlight应用程序和Winfors/WPF应用程序.当我使用带有asp.net mvc的SM时,我已经通过asp.net mvc的应用程序启动初始化了IOC,现在,对于许多项目使用我无法想象IOC配置应该位于的好地方.我也想在服务层制作DI(注入存储库).
在这种情况下,我在哪里加载我的IOC配置以及我将如何在整个项目中使用(比如只在asp.net mvc应用程序中需要控制器工厂)?
我将首先告诉我的项目设置:
我在这里创建了一个bootstrapper类:
Imports StructureMap
Imports DCS.Data
Imports DCS.Services
Public Class BootStrapper
Public Shared Sub ConfigureStructureMap()
ObjectFactory.Initialize(AddressOf StructureMapRegistry)
End Sub
Private Shared Sub StructureMapRegistry(ByVal x As IInitializationExpression)
x.AddRegistry(New MainRegistry())
x.AddRegistry(New DataRegistry())
x.AddRegistry(New ServiceRegistry())
x.Scan(AddressOf StructureMapScanner)
End Sub
Private Shared Sub StructureMapScanner(ByVal scanner As StructureMap.Graph.IAssemblyScanner)
scanner.Assembly("DCS")
scanner.Assembly("DCS.Data")
scanner.Assembly("DCS.Services")
scanner.WithDefaultConventions()
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
我在这里创建了一个控制器工厂:
Imports System.Web.Mvc
Imports StructureMap
Public Class StructureMapControllerFactory
Inherits DefaultControllerFactory
Protected Overrides Function GetControllerInstance(ByVal controllerType As System.Type) As System.Web.Mvc.IController
Return ObjectFactory.GetInstance(controllerType)
End Function …Run Code Online (Sandbox Code Playgroud) 如果我有以下存储库:
public IQueryable<User> Users()
{
var db = new SqlDataContext();
return db.Users;
}
Run Code Online (Sandbox Code Playgroud)
我知道只有在触发查询时才会打开连接:
public class ServiceLayer
{
public IRepository repo;
public ServiceLayer(IRepository injectedRepo)
{
this.repo = injectedRepo;
}
public List<User> GetUsers()
{
return repo.Users().ToList(); // connection opened, query fired, connection closed. (or is it??)
}
}
Run Code Online (Sandbox Code Playgroud)
如果是这种情况,我还需要使我的Repository实现IDisposable吗?
Visual Studio Code Metrics当然认为我应该.
我正在使用IQueryable因为我将查询控制到我的服务层(过滤器,分页等),所以请不要就我使用它的事实进行架构讨论.
BTW - SqlDataContext是我的自定义类,它扩展了Entity Framework的ObjectContext类(所以我可以拥有POCO派对).
所以问题 - 我真的必须实现IDisposable吗?
如果是这样,我不知道这是如何可能的,因为每个方法共享相同的存储库实例.
编辑
我正在使用Depedency Injection(StructureMap)将具体的存储库注入服务层.这个模式跟随app堆栈 - 我正在使用ASP.NET MVC,并且具体服务被注入到控制器中.
换一种说法:
我正在使用混合模式将依赖项注入我的控制器,根据StructureMap文档,这些实例将存储在HttpContext.Current.Items中.
所以,我不能这样做:
using (var repo = new …Run Code Online (Sandbox Code Playgroud) structuremap idisposable iqueryable repository objectcontext
在高层次上,这些如何解决.注射框架有效吗?
我能理解你是否总是通过自定义工厂实例化对象,如:
IUser user = DepInjector.Get<User>();
Run Code Online (Sandbox Code Playgroud)
我猜测发生了什么,无论你在哪里定义映射,它都会查看你想要的类型并尝试找到匹配项,如果找到,它将通过反射实例化类型.
是否有dep.注射.框架可以像:
IUser user = new User();
Run Code Online (Sandbox Code Playgroud)
如果是这样,它将如何获得正确的用户,它在哪里挂钩到CLR来执行此操作?如果是asp.net网站,它有什么不同吗?
在StructureMap中有一种方法可以用一行或一个约定来做这种重复映射吗?
For<IRepository<Mailout>>().Use<MailoutRepository>();
For<IRepository<MailServer>>().Use<MailServerRepository>();
For<IRepository<MailoutStatus>>().Use<MailoutStatusRepository>();
For<IRepository<MailoutTemplate>>().Use<MailoutTemplateRepository>();
For<IRepository<Publication>>().Use<PublicationRepository>();
For<IRepository<Recipient>>().Use<RecipientRepository>();
Run Code Online (Sandbox Code Playgroud) 我已升级到SM 3.0,现在,除了其他重大变化之外,我发现EqualToAppSetting已经消失.
我曾经能做到
.Use<SomeType>().Ctor<SomeType>("connectionStr").EqualToAppSetting("myAppSetting");
Run Code Online (Sandbox Code Playgroud)
当然,myAppSetting从app.config或web.config中提取.
现在有人知道怎么做吗?或其他一些工作?
我最近在我的代码中遇到了以下错误,这使我无法进行调试.我想基于它的接口注入一个实例,如下所示:
MovementController(IMotorController motorController)
Run Code Online (Sandbox Code Playgroud)
但是我不小心使用了这样的具体类型:
MovementController(MotorController motorController)
Run Code Online (Sandbox Code Playgroud)
该项目仍然构建并运行良好,直到我尝试motorController从MovementController实例访问.由于IMotorController访问硬件的底层实现,它必须是单例或我的锁代码.但是,由于我有其他类注入IMotorController,我现在MotorController在对象图中有两个实例,它们都通过串行连接访问硬件.这导致错误,在运行时处于更低的水平,这让我永远调试并找到真正的原因.
如何避免这种类型的错误或为我的StructureMap注册表编写单元测试以捕获这个微妙的错误?
他们在我目前正在工作的IoC中使用StructureMap.
我有一个应用程序类,将实现相同接口的多个属性...我需要绑定不同的实现
......不,我不能这样做: IProvider<T>
例如:
public class MyApplication
{
[SetterProperty]
public IProvider OneProvider { get; set; }
[SetterProperty]
public IProvider TwoProvider { get; set; }
}
public class FooProvider: IProvider {
// I would like to force this one to bind-on OneProvider ...
}
public class BarProvider: IProvider {
// I would like to force this one to bind-on TwoProvider ...
}
Run Code Online (Sandbox Code Playgroud)
例如,在Unity中,有很多方法可以做到这一点;
[Dependency("FooProvider")]
public IProvider OneProvider { get; set; }
[Dependency("BarProvider")]
public IProvider TwoProvider { get; set; }
Run Code Online (Sandbox Code Playgroud)
...但是,StructureMaps …
structuremap ×10
asp.net-mvc ×2
c# ×2
unit-testing ×2
arguments ×1
asp.net ×1
caching ×1
constructor ×1
datacontext ×1
idisposable ×1
iqueryable ×1
linq-to-sql ×1
moq ×1
ninject ×1
repository ×1
soa ×1
wcf ×1