ASP.NET Core 2.0依赖注入默认实例

时间:2017-10-11 18:52:46

标签: c# asp.net dependency-injection asp.net-core asp.net-core-2.0

我正在使用ASP.NET Core 2.0Microsoft.Extensions.DependencyInjection。我有一些课程,我不想指定它的实现,或者我不需要指定。

例如:

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>();
        ...
    }
}

并且我只想IMyToolGeneralMyToolGeneralIOtherOther一起指定,但MyObject没有,因为我有很多这样的课程(验证员,帮助者......)我并不需要指定这些。

我怎样才能在ASP.NET Core 2.0

中执行此操作

修改

我需要ASP.NET Core 2.0 DI可以在DI配置中注入MyObject实例而不指定它。 MyObject没有基类的契约(接口),其构造函数中的所有参数都在DI配置中指定。

编辑II 我重写了类并在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:无法解析类型&#39; ConsoleDI.MyObject&#39;的服务。在尝试激活ConsoleDI.MyService&#39;。

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();
    }
}

2 个答案:

答案 0 :(得分:4)

内置依赖项注入容器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提供了一种方法来构造未在容器中注册的类型的对象,但需要来自要构造的容器。您可以使用ActivatorUtilities.CreateInstance方法创建对象。例如,使用您的服务定义,您可以创建一个MyObject实例,如下所示:

var myObject = ActivatorUtilities.CreateInstance<MyObject>(serviceCollection);

这将自动从容器中获取IOther并将其注入MyObject的构造函数中。 MyObject不需要为此注册,但IOther会这样做。

因此,这仅适用于实例化未在容器中注册的类型。它不适用于其他类型所需的 for dependencies 。依赖注入只能自动为依赖注入容器中注册的依赖项提供实例。

因此,无法通过依赖注入创建MyService对象,因为它的依赖项MyObject未注册。没有办法解决这个问题,如果你想让DI框架为你自动实例化对象,你来注册它。

答案 1 :(得分:0)

您可以通过

将它们添加到DI中
services.AddScoped<MyObject>();

或更复杂的事情,如

services.AddScoped(provider =>
{
    var res = new MyObject
    {
        Message = "Hello World 2"
    };
    return res;
});

您可以自己构建对象。

Sample prj here