为MVC 3实现一点IOC

P.B*_*key 3 c# inversion-of-control asp.net-mvc-3

我正在设计一个允许我模拟我的数据库的设计,以便我可以测试我的观点.我不想阅读关于IOC的完整书籍,因为我现在没有时间.所以,这是我的家常菜.

控制器:

    public ActionResult Milestone()
    {
        var result = SJMServiceFactory.GetService("Milestone");
        return View(result);
    }
Run Code Online (Sandbox Code Playgroud)

厂:

public static class SJMServiceFactory
{
    public static DatabaseCollection_Result<T> GetService(string serviceName)
    {
        switch(serviceName)
        {
            case("Milestone"): return MileStoneService.GetMilestone();
            case ("MilestoneMock"): return MileStoneService.GetMilestone(true);
            default : return default(T);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

里程碑

public class MileStoneService
{
    public MileStoneService()
    {

    }
    public static DatabaseCollection_Result<Milestone> GetMilestone(bool Mock)
    {
        if (Mock)
        {
            DatabaseCollection_Result<Milestone> mileStones = new DatabaseCollection_Result<Milestone>();
            Milestone milestone1 = new Milestone();
            milestone1.Name = "New";
            Milestone milestone2 = new Milestone();
            milestone2.Name = "Assessment";
            mileStones.Results.Add(milestone1);
            mileStones.Results.Add(milestone2);
            return mileStones;
        }
        else
            return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想我需要从我的工厂返回一个接口,而不是我试过的那种Generic类型.我不知道如何创建一个适用于我所有模型的界面,是错误的方向吗?

Mic*_*ins 7

没有阅读整本书(是否存在一个?IoC在事物计划中是一个非常小的主题):

控制器:

private readonly IMilestoneService milestoneSerivce;

public MilestoneController(IMilestoneService milestoneService)
{
    this.milestoneService = milestoneService;
}

public ActionResult Milestone()
{
    var result = milestoneService.GetMilestones();
    return View(result);
}
Run Code Online (Sandbox Code Playgroud)

IMilestoneService.cs

public interface IMilestoneService
{
    DatabaseCollection_Result<Milestone> GetMilestones();
}
Run Code Online (Sandbox Code Playgroud)

MilestoneService.cs

public class MilestoneService : IMilestoneService
{
    public DatabaseCollection_Result<Milestone> GetMilestones()
    {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

MockMilestoneService.cs:

public class MockMilestoneService : IMilestoneService
{
    public DatabaseCollection_Result<Milestone> GetMilestones()
    {
        DatabaseCollection_Result<Milestone> mileStones = new DatabaseCollection_Result<Milestone>();
        Milestone milestone1 = new Milestone();
        milestone1.Name = "New";
        Milestone milestone2 = new Milestone();
        milestone2.Name = "Assessment";
        mileStones.Results.Add(milestone1);
        mileStones.Results.Add(milestone2);
        return mileStones;
    }
} 
Run Code Online (Sandbox Code Playgroud)

Global.asax中:

ObjectFactory.Configure(x => {
    x.For<IMilestoneService>().Use<MilestoneService>();
    // uncomment for test
    //x.For<IMilestoneService>().Use<MockMilestoneService>();
});
Run Code Online (Sandbox Code Playgroud)

这使用了StructureMap,但我想Ninject连接依赖关系的方法是类似的.从来没有使用Ninject我不确定,但看起来它可能是这样的:

Bind<IMilestoneService>().To<MilestoneService>();
Run Code Online (Sandbox Code Playgroud)

一般来说,虽然我不打算创建一个全新的类来测试你的视图,但是我会使用一个模拟框架(如Moq)来创建模拟对象并将它们传递给View,然后使用关于ViewResult的Assertions来确定它是否有效正确.

如果您正在进行交互式测试并希望与数据库分离,这可能是一种正常的方法.


que*_*rin 5

不要害怕学习曲线.IoC是一个相当简单的概念.

Ninject是我收集的第一个容器,它顺利进行.在任何时候我真正努力的唯一一点是如何组织所有绑定,但即使这只是大型应用程序中的一个问题.

YMMV,但我想说只是潜入Ninject或类似的是比DIY更好的时间投入.

使用Ninject的IoC仅在几个地方使用代码.

1:将接口绑定到实现:

public class ServiceModule : NinjectModule
{
    public override void Load() {
        Bind<Common.Billing.AuthorizeNet.IBillingGatewayParametersFactory>().To<AuthorizeNetParameterFactory>();
        Bind<Common.Billing.IBillingGateway>().To<Common.Billing.AuthorizeNet.BillingGateway>();
    }
}
Run Code Online (Sandbox Code Playgroud)

2:使用构造函数参数将依赖项传递给类:

public class BillPayingService
{
    private readonly IBillingGateway _billingGateway;

    public BillPayingService(
            IBillingGateway billingGateway
        )
    {
        _billingGateway = billingGateway;
    }

    public void PayBills()
    {
       // ....
    }
}
Run Code Online (Sandbox Code Playgroud)

3:在应用程序启动时初始化容器:

public static class Ioc
{
    public static void Initialize()
    {
        var modules = new INinjectModule[] {
            new ServicesModule(),
            new DataModule()
                            new VideoProcessing.NinjectModule()
        };


        IKernel kernel = new Ninject.StandardKernel(modules);
    }
}
Run Code Online (Sandbox Code Playgroud)