简体   繁体   English

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

[英]ASP.NET Core 2.0 Dependency Injection default instance

I'm using ASP.NET Core 2.0 and Microsoft.Extensions.DependencyInjection . 我正在使用ASP.NET Core 2.0Microsoft.Extensions.DependencyInjection I have a few class where I don't want to specified its implementation or I don't need to specified. 我有几个课我不想指定它的实现,或者我不需要指定。

For example: 例如:

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

and I want to specified only IMyToolGeneral with MyToolGeneral and IOther with Other , but MyObject not, because I have a lot of classes like this (validators, helpers, ...) and I don't need to specified these. 我想只有指定IMyToolGeneralMyToolGeneralIOtherOther ,但MyObject不行,因为我有很多课是这样的(验证者,帮助者,......),我并不需要指定这些。

how can I do that in ASP.NET Core 2.0 ? 我怎么能在ASP.NET Core 2.0做到这一点?

edit 编辑

I need that ASP.NET Core 2.0 DI can inject a instance of MyObject without specified it in DI configuration. 我需要ASP.NET Core 2.0 DI可以在DI配置中注入MyObject实例而不指定它。 MyObject haven't a contract (interface) o base class, and all parameters in its constructor are specified in DI configuration. MyObject没有基类的契约(接口),并且其构造函数中的所有参数都在DI配置中指定。

edit II I rewrite classes and include a example in Unity (that works) and the same example in MS DI (that dont' work) 编辑II我重写类并在Unity(包括工作)中包含一个示例,在MS DI中包含相同的示例(不工作)

unity example (work) 统一的例子(工作)

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 (don't work) Unhandled Exception: System.InvalidOperationException: Unable to resolve service for type 'ConsoleDI.MyObject' while attempting to activate 'ConsoleDI.MyService'. 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();
    }
}

The built-in dependency injection container, Microsoft.Extensions.DependencyInjection , does not support convention based registration. 内置依赖项注入容器Microsoft.Extensions.DependencyInjection不支持基于约定的注册。 So when you would usually set up some convention that eg all types within a namespace will be registered as a transient dependency, this does not work out of the box with the standard container. 因此,当您通常设置一些约定时,例如命名空间中的所有类型都将被注册为瞬态依赖项,这与标准容器的开箱即用。

If you still want to do this, you would either have to change the dependency injection container to a more powerful one (remember that the built-in container is by design a very slim one), or create your own convention-based logic to register your dependencies. 如果你仍然想要这样做,你要么必须将依赖注入容器更改为更强大的容器(请记住,内置容器设计非常简单),或者创建自己的基于约定的逻辑来注册你的依赖。 For example, you could simply loop through the current assembly and check for all types within a certain namespace and register those: 例如,您可以简单地遍历当前程序集并检查某个名称空间中的所有类型并注册它们:

var types = Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => t.Namespace == "Your.Custom.Namespace");

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

If you don't want to register all the types, there is one more thing you can do. 如果您不想注册所有类型,还可以做一件事。 There are the 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 method to create an object. 您可以使用ActivatorUtilities.CreateInstance方法创建对象。 For example, with your service definition, you could create a MyObject instance like this: 例如,使用服务定义,您可以创建一个MyObject实例,如下所示:

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

This will automatically get the IOther from the container and inject it into the constructor of MyObject . 这将自动从容器中获取IOther并将其注入MyObject的构造函数中。 MyObject does not need to be registered for this, but IOther does. MyObject不需要为此注册,但IOther确实如此。

So this only works for instantiating types that are not registered in the container. 因此,这仅适用于实例化未在容器中注册的类型。 It does not work for dependencies that are required by other types. 它不适用于其他类型所需的依赖项 Dependency injection can only automatically provide instances for those dependencies that are registered in the dependency injection container. 依赖注入只能自动为依赖注入容器中注册的依赖项提供实例。

So you cannot create a MyService object through dependency injection since its dependency, MyObject , is not registered. 因此,您无法通过依赖项注入创建MyService对象,因为它的依赖项MyObject未注册。 There is no way around this, you have to register it if you want the DI framework to automatically instantiate the object for you. 如果您希望DI框架为您自动实例化对象,则必须注册它。

You can add them to DI via 您可以将它们添加到DI via

services.AddScoped<MyObject>();

or something more complicated like 或者更复杂的东西

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

where you can constructor the object yourself. 你可以在哪里构建对象。

Sample prj here 这里有样品prj

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM