1

请温柔,我对于新手,这个IOC/MVC的事情,但我想。我了解DI用于测试目的的价值以及IoC在运行时如何解决依赖关系,并且已经通过了几个适用于您的标准CRUD操作的示例...ASP.NET MVC和IOC - 链注入

我开始一个新项目并且无法上来用干净的方式来完成用户权限。我的网站主要是通过任何带有功能的页面(注册,常见问题,关于我们等)进行登录。我有一个自定义的身份,有几个额外的属性,控制访问数据...所以... ...

使用Ninject,我已经绑定具体类型*的方法(Bind<MyIdentity>().ToMethod(c => MyIdentity.GetIdentity());,这样,当我添加MyIdentity一个构造函数,它是基于方法调用的结果注入的。

这一切工作正常。是否适合(从GetIdentity()方法)直接查询请求cookies对象(通过FormsAuthentication)?在测试控制器时,我可以通过在一个身份,但GetIdentity()方法将基本上不可测...

此外,在的getIdentity()米方法,我会查询数据库。我应该手动创建一个存储库的具体实例吗?

还是有更好的办法一起?

回答

4

我认为你是相当正确的轨道上,因为你从你的单元测试抽象掉数据库通信和ASP.NET的依赖。不要担心你无法在测试中测试所有的东西。在您的应用程序中始终存在不可测试的代码行。 GetIdentity就是一个很好的例子。在您的应用程序的某处,您需要与特定于框架的API进行通信,并且您的单元测试无法涵盖此代码。

可能仍有改进的余地,但。虽然未经测试的GetIdentity不是问题,但它实际上可由应用程序调用。它只是挂在那里,等着有人不小心打电话给它。那么为什么不抽象身份的创造。例如,创建一个知道如何为当前上下文获取正确标识的抽象工厂。你可以注入这个工厂,而不是注入身份本身。这使您可以在应用程序的组合根目录附近定义一个实现,并且可以在应用程序的其余部分之外进行定义。除此之外,代码更清楚地传达了正在发生的事情。没有人需要问“我实际上得到了哪个身份?”,因为他们所称的工厂的方法很明显。

下面是一个例子:

public interface IIdentityProvider 
{ 
    // Bit verbose, but veeeery clear, 
    // but pick another name if you like, 
    MyIdentity GetIdentityForCurrentUser(); 
} 

在你的作文根,你可以有一个这样的实现:

private sealed class AspNetIdentityProvider : IIdentityProvider 
{ 
    public MyIdentity GetIdentityForCurrentUser() 
    { 
     // here the code of the MyIdentity.GetIdentity() method. 
    } 
} 

作为招有时我有我的测试对象,对工厂和产品两个,只是为了方便在单元测试。例如:

private sealed class FakeMyIdentity 
    : FakeMyIdentity, IIdentityProvider 
{ 
    public MyIdentity GetIdentityForCurrentUser() 
    { 
     // just returning itself. 
     return this; 
    } 
} 

这样你可以注入一个FakeMyIdentity在期望一个IIdentityProvider构造。我发现这不会牺牲测试的可读性(这很重要)。 当然你会希望有尽可能少的代码尽可能在AspNetIdentityProvider,因为你不能测试它(自动)。同时确保你的类不依赖任何框架特定的部分。如果是这样,你也需要抽象。

我希望这是有道理的。

1

有两件事情我还挺有什么不同......在这里

  1. 我会使用一个自定义的IPrincipal与所有身份验证需求所需对象的属性。然后,我会将它与自定义Cookie创建和AuthenticateRequest事件结合使用,以避免每次请求都会调用数据库。

  2. 如果我的IPrincipal/Identity在另一个类中需要,我会将它作为方法参数传递,而不是将它作为它自己的类的依赖项。
    当沿着这条路线走时,我使用自定义模型粘合剂,这样他们就成为我的行为的参数,而不是奇迹般地出现在我的动作方法中。
    注意:这只是我一直在做的事情,所以拿一粒盐。

对不起,这可能会抛出更多的问题比答案。随意提出更多关于我的方法的问题。

+0

+1。如果可能,我同意使用'IPrinciple'接口。这是.NET的核心概念,可以在整个应用程序中使用,而不会有任何问题。 – Steven 2011-03-10 09:08:14

+0

我已经考虑过使用模型绑定器并将它传递给方法,但由于每一次调用(除了我的通用内容控制器中的那些)都需要身份,我觉得它违反了DRY,并认为更好的解决方案是拥有它通过控制器级别传入。 – 2011-03-10 15:29:31