ASP.NET Core 2.0 依赖注入默认实例
ASP.NET Core 2.0 Dependency Injection default instance
我正在使用 ASP.NET Core 2.0
和 Microsoft.Extensions.DependencyInjection
。我有几个 class 不想指定其实现或不需要指定。
例如:
public interface IMyService
{
void WriteSomething();
}
public class MyService : IMyService
{
private readonly MyObject myObject;
public MyService(MyObject myObject)
{
this.myObject = myObject;
}
public void WriteSomething()
{
this.myObject.Write();
}
}
public interface IOther
{
string GetName();
}
public class Other : IOther
{
public string GetName()
{
return "james bond";
}
}
public class MyObject
{
private readonly IOther other;
public MyObject(IOther other)
{
this.other = other;
}
public void Write()
{
Console.WriteLine(string.Concat("hi ", this.other.GetName()));
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IOther, Other>();
services.AddScoped<IMyService, MyService>();
...
}
}
我只想用 MyToolGeneral
指定 IMyToolGeneral
,用 Other
指定 IOther
,但 MyObject
不行,因为我有很多 class像这样(验证器、帮助器……),我不需要指定这些。
我如何在 ASP.NET Core 2.0
中做到这一点?
编辑
我需要 ASP.NET Core 2.0 DI
可以注入 MyObject 的实例,而无需在 DI 配置中指定它。 MyObject 没有基础合约(接口)class,其构造函数中的所有参数都在 DI 配置中指定。
编辑二
我重写 classes 并在 Unity 中包含一个示例(有效),在 MS DI 中包含相同的示例(无效)
统一示例(工作)
class Program
{
static void Main(string[] args)
{
var container = UnityConfig();
var service = container.Resolve<IMyService>();
service.WriteSomething();
Console.ReadKey();
}
static UnityContainer UnityConfig()
{
var container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
container.RegisterType<IOther, Other>();
return container;
}
}
MS DI(不工作)
未处理的异常:System.InvalidOperationException:尝试激活 'ConsoleDI.MyService'.
时无法解析类型 'ConsoleDI.MyObject' 的服务
class Program
{
static void Main(string[] args)
{
var serviceProvider = new ServiceCollection()
.AddTransient<IMyService, MyService>()
.AddTransient<IOther, Other>()
.BuildServiceProvider();
var service = serviceProvider.GetService<IMyService>();
service.WriteSomething();
Console.ReadKey();
}
}
您可以通过
将它们添加到 DI
services.AddScoped<MyObject>();
或者更复杂的东西,比如
services.AddScoped(provider =>
{
var res = new MyObject
{
Message = "Hello World 2"
};
return res;
});
您可以自己构造对象。
内置依赖注入容器Microsoft.Extensions.DependencyInjection
不支持基于约定的注册。因此,当您通常会设置一些约定时,例如命名空间中的所有类型都将注册为瞬态依赖项,这不适用于标准容器。
如果您仍然想这样做,您要么必须将依赖注入容器更改为更强大的容器(请记住,内置容器是设计一个非常苗条的一个),或者创建你自己的基于约定的逻辑来注册你的依赖项。例如,您可以简单地遍历当前程序集并检查特定命名空间内的所有类型并注册这些类型:
var types = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.Namespace == "Your.Custom.Namespace");
foreach (var type in types)
{
services.AddTransient(type);
}
如果您不想注册 所有 类型,您还可以做一件事。有 activator utilities which offer a way to construct objects of types that are not registered themselves in the container, but require dependencies from the container to be constructed. You can use the ActivatorUtilities.CreateInstance
方法来创建一个对象。例如,对于您的服务定义,您可以像这样创建一个 MyObject
实例:
var myObject = ActivatorUtilities.CreateInstance<MyObject>(serviceCollection);
这会自动从容器中获取IOther
并注入到MyObject
的构造函数中。 MyObject
不需要为此注册,但 IOther
需要。
因此这仅适用于实例化未在容器中注册的类型。它不适用于 其他类型所需的依赖项 。依赖注入只能自动为那些在依赖注入容器中注册的依赖提供实例。
所以你不能通过依赖注入创建一个MyService
对象,因为它的依赖MyObject
没有注册。没有办法解决这个问题,如果您希望 DI 框架自动为您实例化对象,您必须注册它。
我正在使用 ASP.NET Core 2.0
和 Microsoft.Extensions.DependencyInjection
。我有几个 class 不想指定其实现或不需要指定。
例如:
public interface IMyService
{
void WriteSomething();
}
public class MyService : IMyService
{
private readonly MyObject myObject;
public MyService(MyObject myObject)
{
this.myObject = myObject;
}
public void WriteSomething()
{
this.myObject.Write();
}
}
public interface IOther
{
string GetName();
}
public class Other : IOther
{
public string GetName()
{
return "james bond";
}
}
public class MyObject
{
private readonly IOther other;
public MyObject(IOther other)
{
this.other = other;
}
public void Write()
{
Console.WriteLine(string.Concat("hi ", this.other.GetName()));
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IOther, Other>();
services.AddScoped<IMyService, MyService>();
...
}
}
我只想用 MyToolGeneral
指定 IMyToolGeneral
,用 Other
指定 IOther
,但 MyObject
不行,因为我有很多 class像这样(验证器、帮助器……),我不需要指定这些。
我如何在 ASP.NET Core 2.0
中做到这一点?
编辑
我需要 ASP.NET Core 2.0 DI
可以注入 MyObject 的实例,而无需在 DI 配置中指定它。 MyObject 没有基础合约(接口)class,其构造函数中的所有参数都在 DI 配置中指定。
编辑二 我重写 classes 并在 Unity 中包含一个示例(有效),在 MS DI 中包含相同的示例(无效)
统一示例(工作)
class Program
{
static void Main(string[] args)
{
var container = UnityConfig();
var service = container.Resolve<IMyService>();
service.WriteSomething();
Console.ReadKey();
}
static UnityContainer UnityConfig()
{
var container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
container.RegisterType<IOther, Other>();
return container;
}
}
MS DI(不工作) 未处理的异常:System.InvalidOperationException:尝试激活 'ConsoleDI.MyService'.
时无法解析类型 'ConsoleDI.MyObject' 的服务class Program
{
static void Main(string[] args)
{
var serviceProvider = new ServiceCollection()
.AddTransient<IMyService, MyService>()
.AddTransient<IOther, Other>()
.BuildServiceProvider();
var service = serviceProvider.GetService<IMyService>();
service.WriteSomething();
Console.ReadKey();
}
}
您可以通过
将它们添加到 DIservices.AddScoped<MyObject>();
或者更复杂的东西,比如
services.AddScoped(provider =>
{
var res = new MyObject
{
Message = "Hello World 2"
};
return res;
});
您可以自己构造对象。
内置依赖注入容器Microsoft.Extensions.DependencyInjection
不支持基于约定的注册。因此,当您通常会设置一些约定时,例如命名空间中的所有类型都将注册为瞬态依赖项,这不适用于标准容器。
如果您仍然想这样做,您要么必须将依赖注入容器更改为更强大的容器(请记住,内置容器是设计一个非常苗条的一个),或者创建你自己的基于约定的逻辑来注册你的依赖项。例如,您可以简单地遍历当前程序集并检查特定命名空间内的所有类型并注册这些类型:
var types = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.Namespace == "Your.Custom.Namespace");
foreach (var type in types)
{
services.AddTransient(type);
}
如果您不想注册 所有 类型,您还可以做一件事。有 activator utilities which offer a way to construct objects of types that are not registered themselves in the container, but require dependencies from the container to be constructed. You can use the ActivatorUtilities.CreateInstance
方法来创建一个对象。例如,对于您的服务定义,您可以像这样创建一个 MyObject
实例:
var myObject = ActivatorUtilities.CreateInstance<MyObject>(serviceCollection);
这会自动从容器中获取IOther
并注入到MyObject
的构造函数中。 MyObject
不需要为此注册,但 IOther
需要。
因此这仅适用于实例化未在容器中注册的类型。它不适用于 其他类型所需的依赖项 。依赖注入只能自动为那些在依赖注入容器中注册的依赖提供实例。
所以你不能通过依赖注入创建一个MyService
对象,因为它的依赖MyObject
没有注册。没有办法解决这个问题,如果您希望 DI 框架自动为您实例化对象,您必须注册它。