asp.net mvc中的依赖注入模型

时间:2014-07-08 22:51:46

标签: c# .net asp.net-mvc architecture

我目前正在开发一个.NET MVC 5站点,我对提高质量有疑问。我从另一个开发人员那里拿到了这个项目,整个项目都有相当多的代码味道,所以我正在尝试清理项目。我遇到的问题是大量的类耦合,因此内聚力低。 (为了保护开发人员,他的前端JS代码非常棒,并且从静态分析工具中获得了非常可靠的分数)。我目前的问题与项目中助手的类耦合有关。这是当前的实施:

...
Type iaccounthelpertype = typeof(IAccountsHelper), igettabletype = typeof(IGettable);
List<Tuple<IAccountsHelper, IGettable>> valid = new List<Tuple<IAccountsHelper, IGettable>>();
// Get all the types that implement IAccountsHelper and IGettable
IEnumerable<Type> types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => iaccounthelpertype.IsAssignableFrom(p) && igettabletype.IsAssignableFrom(p))
    .Select(x => x);

foreach (Type type in types)
{
    MethodInfo methodInfo = type.GetMethod("Get");
    try
    {
        methodInfo = methodInfo.MakeGenericMethod(typeof(T));
        IAccountsHelper helper = methodInfo.Invoke(null, null) as IAccountsHelper;
        valid.Add(Tuple.Create<IAccountsHelper, IGettable>(helper, helper as IGettable));
    }
    catch (NullReferenceException nullref)
    {
        // this is bad. The new object does not implement the proper static method. So we will carry this exception through.
        throw new Exception(type.Name + " does not implement the static generic method Get");
    }
    catch (ArgumentException e)
    {
        continue;
    }
}
...

此代码允许以下实现(上面的函数名称称为Get)

IAccountsHelper helper = TheParentClass<UserPrincipal>.Get();

所以现在任何使用“helper”对象的代码都可以期望该类执行的任何操作都是UserPrincipal类型(因此就像创建用户的ActiveDirectory助手一样)。到目前为止,对于任何需要帮助器的代码单元而言,它具有更好的实现,而没有更高的耦合率,增加了内聚力。它只是调用这个类,告诉它应该使用什么类型的对象,并且该函数将它映射到适当的类。我做了所有这些因为我无法找到一种方法来处理MVC / web api项目中的依赖注入。但是我觉得这段代码很脏,而且我认为它们可能是一种更好的方式来实现我的目标。有没有人对我能做什么有什么建议,或者这段代码是不是很脏等等?

作为一个注释,我正在使用visual studio代码度量窗口来获得项目的类耦合,从436减少到401,代码为5,909行。 (我发现你需要两个人对内聚有一个很好的估计)。

1 个答案:

答案 0 :(得分:0)

ASP.NET MVC实际上对依赖注入框架有很好的支持。其中最受欢迎的是Ninject。如果您使用NuGet包管理器将Ninject MVC 5包带入您的Web项目,它将自行完成大部分设置工具。然后你只需要在其设置区域添加一个绑定:

Bind<IAccountsHelper>().To<UserPrincipal>();

然后在需要其中一个的任何类中使用构造函数注入:

public MyController(IAccountsHelper accountsHelper)
{
    _accountsHelper = accountsHelper;
}