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

3

我正在使用 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>();
        ...
    }
}

我想指定只有IMyToolGeneral使用MyToolGeneral,并且只有IOther使用Other,但是不指定MyObject,因为我有很多类似的类(验证器,帮助程序等),而我不需要指定它们。
ASP.NET Core 2.0中如何实现?
编辑:
我需要ASP.NET Core 2.0 DI能够注入一个MyObject实例,而无需在DI配置中指定它。 MyObject没有契约(接口)或基类,并且其构造函数中的所有参数都在DI配置中指定。
第二次编辑:
我重写了类并在Unity中包含了一个示例(可行),以及在MS DI中包括相同的示例(不可行)。
Unity示例(可行):
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();
    }
}

也许是 services.AddTransient<MyObject>(); - Ivan Milosavljevic
@Kirk Ready,我包含了更多细节。 - andres descalzo
@IvanMilosavljevic 我需要避免这种情况。 - andres descalzo
@IvanMilosavljevic 是的,我知道,但我需要避免这种情况。在Unity中可以实现。 - andres descalzo
1
你是否严格使用微软 DI?还有 autofac 属性注入 - Ivan Milosavljevic
@IvanMilosavljevic 是的,我只能使用微软 DI。 - andres descalzo
2个回答

4
内置的依赖注入容器Microsoft.Extensions.DependencyInjection不支持基于约定的注册。因此,当您通常设置一些约定时,例如将命名空间中的所有类型注册为瞬态依赖项,这在标准容器中无法直接实现。
如果您仍想这样做,您需要更改依赖注入容器为更强大的容器(请记住,内置容器设计上非常轻巧),或者创建自己基于约定的逻辑来注册您的依赖项。例如,您可以简单地循环遍历当前程序集并检查某个命名空间中的所有类型,并将其注册。
var types = Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => t.Namespace == "Your.Custom.Namespace");

foreach (var type in types)
{
    services.AddTransient(type);
}

如果您不想注册所有类型,还有一件事情可以做。这里有一个激活工具,提供了一种构造未在容器中注册的类型对象的方法,但需要从容器中获取依赖项进行构造。您可以使用ActivatorUtilities.CreateInstance方法来创建对象。例如,使用您的服务定义,您可以像这样创建MyObject实例:

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

这将自动从容器中获取IOther并将其注入到MyObject的构造函数中。对于此过程,MyObject不需要注册,但IOther需要注册。
因此,它仅适用于在容器中未注册的类型。这不能用于其他类型所需的依赖项。依赖项注入只能为那些在依赖项注入容器中注册的依赖项自动提供实例。
由于它的依赖性MyObject未注册,因此无法通过依赖项注入来创建MyService对象。如果您想要DI框架自动实例化该对象,则必须注册它。

1
如果有人采取主动措施,创建这样的扩展将更容易被重复使用。如果微软拒绝将它们添加到自己的库中,没有任何阻止任何人为大众创建自己的NuGet.org包来提供它们的东西。 - NightOwl888
3
@NightOwl888,没有任何事情可以阻止做到这一点。如果您在NuGet上查看,实际上有相当多的扩展包可用于框架的某些部分。尽管如此,个人而言,我不太喜欢基于约定的DI设置。如果您确实需要它们,那么应该非常明确地表明正在发生这种情况。这几行代码并不会产生什么影响,但可以非常清楚地传达意图。 - poke

0

你可以通过 DI 将它们添加进去。

services.AddScoped<MyObject>();

或者更复杂的东西,比如

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

您可以自己构造对象。

这里有样本项目


是的,我知道这个,但我需要避免这种情况。在Unity中是可能实现的。 - andres descalzo
抱歉,我没听懂。你有Unity的示例吗? - spottedmahn
1
我包含了一个例子 - andres descalzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接