ASP.Net MVC 6:递归依赖注入
ASP.Net MVC 6: Recursive Dependency Injection
仍在探索新的 ASP.NET MVC5,现在内置 DI!
到目前为止没有问题,我可以注入我的处理程序(我不喜欢术语服务,因为它向我定义了一个平台中立的接口):
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
services.AddMvc();
}
工作正常,强类型配置对象 "AppSettings" 也工作得很好。
控制器中的注入也同样有效。
但现在我崩溃了:我将我的数据访问与处理程序分开了,显然我也想注入它们:
public class UserEndPointConfigurationHandler
{
private readonly DataAccess.UserEndPointAccess _access;
public UserEndPointConfigurationHandler(DataAccess.UserEndPointAccess access)
{
_access = access;
}
但是糟糕,无法解析 UserEndPointAccess。所以看起来即使我直接请求 DI 一个带有无参数构造函数的 Class,我也需要注册它。对于这种情况,我当然应该接口并注册它们,但这对我也注入的内部助手 类 意味着什么?
根据文档:http://docs.asp.net/en/latest/fundamentals/dependency-injection.html#recommendations 以及我找到的示例,世界上所有人似乎都只在控制器和某些存储库之间进行通信。没有业务层,也没有 Class 组件中不同抽象级别的元素。
Microsoft DI 方法是否与优秀的 Unity 方法完全不同,在 Unity 中我真的可以像我想要的那样细粒度地解耦?
提前致谢。
马蒂亚斯
编辑@Nightowl:我在这里添加我的答案,因为它有点长。
首先,如果我请求一个混凝土类型,Unity 会自动创建实例。这允许我注入我注册的类型和类型,如 Helper 类 等。我不需要。这种组合让我可以在任何地方使用 DI。
另外,在您的示例中,我需要知道 WebGui 中的数据访问,这是非常紧密的耦合。嗯,我知道有通过反射解决这个问题的方法,但我希望微软在这个主题中做点什么,但这可能意味着很大的改变。
还允许 Unity 存储实例或说明如何创建它们,这是目前缺少的另一个重要功能。
可能我只是被宠坏了,精致的 DI 库做了什么,可能它们也做了很多,但根据我的信息,目前 Microsoft 实现只是一个巨大的降级。
MVC 核心遵循 composition root 模式,其中 对象图 是根据一组实例化指令创建的。我认为您误解了 IServiceCollection
的用途。它不存储实例,它存储有关如何创建实例的说明。直到对象图中某处的构造函数请求一个作为构造函数参数时,实例才真正创建。
所以,简而言之,您的服务(您称为 UserEndPointAccess
)在您请求时未被实例化的原因是您没有配置 IServiceCollection
以及有关如何创建的说明它。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
// Need a way to instantiate UserEndPointAccess via DI.
services.AddSingleton(typeof(DataAccess.UserEndPointAccess));
services.AddMvc();
}
So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that.
如果正确执行 DI,每个服务 class 将只有一个构造函数。如果你有多个,它被称为 bastard injection anti-pattern,这实际上意味着你通过添加对它们的引用作为外部默认值,将你的 class 定义与其他 class 紧密耦合。
是的,您需要注册所需的每种类型(这不是 MVC 默认注册的一部分)。在Unity中也是如此。
仍在探索新的 ASP.NET MVC5,现在内置 DI!
到目前为止没有问题,我可以注入我的处理程序(我不喜欢术语服务,因为它向我定义了一个平台中立的接口):
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
services.AddMvc();
}
工作正常,强类型配置对象 "AppSettings" 也工作得很好。
控制器中的注入也同样有效。 但现在我崩溃了:我将我的数据访问与处理程序分开了,显然我也想注入它们:
public class UserEndPointConfigurationHandler
{
private readonly DataAccess.UserEndPointAccess _access;
public UserEndPointConfigurationHandler(DataAccess.UserEndPointAccess access)
{
_access = access;
}
但是糟糕,无法解析 UserEndPointAccess。所以看起来即使我直接请求 DI 一个带有无参数构造函数的 Class,我也需要注册它。对于这种情况,我当然应该接口并注册它们,但这对我也注入的内部助手 类 意味着什么?
根据文档:http://docs.asp.net/en/latest/fundamentals/dependency-injection.html#recommendations 以及我找到的示例,世界上所有人似乎都只在控制器和某些存储库之间进行通信。没有业务层,也没有 Class 组件中不同抽象级别的元素。
Microsoft DI 方法是否与优秀的 Unity 方法完全不同,在 Unity 中我真的可以像我想要的那样细粒度地解耦?
提前致谢。
马蒂亚斯
编辑@Nightowl:我在这里添加我的答案,因为它有点长。 首先,如果我请求一个混凝土类型,Unity 会自动创建实例。这允许我注入我注册的类型和类型,如 Helper 类 等。我不需要。这种组合让我可以在任何地方使用 DI。
另外,在您的示例中,我需要知道 WebGui 中的数据访问,这是非常紧密的耦合。嗯,我知道有通过反射解决这个问题的方法,但我希望微软在这个主题中做点什么,但这可能意味着很大的改变。
还允许 Unity 存储实例或说明如何创建它们,这是目前缺少的另一个重要功能。
可能我只是被宠坏了,精致的 DI 库做了什么,可能它们也做了很多,但根据我的信息,目前 Microsoft 实现只是一个巨大的降级。
MVC 核心遵循 composition root 模式,其中 对象图 是根据一组实例化指令创建的。我认为您误解了 IServiceCollection
的用途。它不存储实例,它存储有关如何创建实例的说明。直到对象图中某处的构造函数请求一个作为构造函数参数时,实例才真正创建。
所以,简而言之,您的服务(您称为 UserEndPointAccess
)在您请求时未被实例化的原因是您没有配置 IServiceCollection
以及有关如何创建的说明它。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
// Need a way to instantiate UserEndPointAccess via DI.
services.AddSingleton(typeof(DataAccess.UserEndPointAccess));
services.AddMvc();
}
So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that.
如果正确执行 DI,每个服务 class 将只有一个构造函数。如果你有多个,它被称为 bastard injection anti-pattern,这实际上意味着你通过添加对它们的引用作为外部默认值,将你的 class 定义与其他 class 紧密耦合。
是的,您需要注册所需的每种类型(这不是 MVC 默认注册的一部分)。在Unity中也是如此。