Нужно ли проверять нулевые значения с помощью конструктора? - PullRequest
0 голосов
/ 18 октября 2018

Я использую инъекцию .NET Core.В обзоре кода от коллеги он поднял вопрос, следует ли мне проверять наличие нулевых значений для внедренных зависимостей в контроллерах.

Поскольку среда отвечает за создание экземпляра службы, мне кажется, что онабудет заботиться о любых ошибках и никогда не будет иметь нулевую зависимость значения для конструктора.У меня нет никаких фактических доказательств этого, поэтому я хотел бы знать, возможно ли, что проверка нуля может быть необходима.

Например, должен ли я проверить, является ли 'myService' нулем вследующий код?(Предполагается, что код настроен на использование DI)

public class MyController
{
    private readonly IMyService _myService;

    public MyController(IMyService myService) 
    {
        _myService = myService;
    }
}

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Чтобы убрать очевидное, нет ничего плохого в выполнении нулевой проверки в вашем конструкторе.


Существует два метода получения служб DI из инфраструктуры.

Первый - GetService<T>().Это будет возвращать нулевое значение, если такая служба не была зарегистрирована.

Вторым является GetRequiredService<T>(). выдает исключение , если служба не может быть найдена.

Оба эти метода выдают исключения, если они не могут полностью создать экземпляр службы, которую вы запрашиваете.

class Program
{
    static void Main(string[] args)
    {
        var services = new ServiceCollection()
            .AddTransient<IServiceB, ServiceB>()
            .BuildServiceProvider();

        var servB = services.GetService<IServiceB>();
    }
}

public interface IServiceA { }
public interface IServiceB { }

public class ServiceA : IServiceA { }
public class ServiceB : IServiceB { public ServiceB(IServiceA a) { } }

В этом примере для ServiceB требуется IServiceA, но A не добавляется в граф зависимостей.Последний метод вызовет исключение:

System.InvalidOperationException: 'Невозможно разрешить службу для типа' DITests.IServiceA 'при попытке активировать' DITests.ServiceB '.'

Если бы я вместо этого сделал services.GetService<IServiceA>(), я бы получил нулевое значение.


Вы можете убедиться в этом сами, посмотрев исходный код GitHub .При вызове любого из методов он в конечном итоге перейдет к методу CreateConstructorCallSite.Это вызывает исключение, если он не может разрешить зависимости вашего типа.


Что касается ASP.Net Core MVC, он использует GetRequiredService<>() для получения ваших контроллеров от DIgraph.


В заключение, нет, вам не требуется для выполнения нулевых проверок объектов DI в вашем конструкторе, если вы используете чистый Microsoft DI framework.Как сказал Камило Теревинто, фреймворк не позволяет этого.

Как отмечается в вашем посте, я не видел письменного документа Microsoft, в котором прямо говорится, что вам не нужно

Если вы передаетев IServiceProvider в качестве аргумента конструктора, и вы разрешаете сервисы из конструктора, , затем вам нужно будет выполнить нулевые проверки.

0 голосов
/ 18 октября 2018

Нужно ли проверять нулевые значения с помощью конструктора?

Это зависит.

  • Этот внутренний код используется вами и (возможно)некоторые товарищи по команде в (к счастью) среде проверки кода?

Не надо.Это необязательно.Фреймворк не позволяет этого.

  • Этот код находится в публичной библиотеке, используется несколькими людьми или фактически не используется после внедрения зависимости?

Тогда сделайте это.Ручная инстанция может привести к возникновению исключения NullReferenceException, которое трудно отследить.

При этом можно использовать что-то вроде этого:

public MyController(IMyService myService) 
{
    if (myService == null)
    {
        throw new ArgumentNullException(nameof(myService));
    }

    _myService = myService;
}

Это очень дешевая проверка, и ее гораздо прощеотследить, если кто-то пропустит null по какой-то причине.

...