"CA2000: избавьтесь от объекта перед потерей контекста", создавая контейнер Unity
Я использую следующий код, где я получаю fxCop voilation CA2000: Удалите объект перед потерей области действия:
private static IUnityContainer BuildContainer()
{
var container = new UnityContainer().LoadConfiguration();
return container;
}
Чтобы устранить это нарушение, я использовал следующий код:
private static IUntyContainer BuildContainer()
{
using(var container = new UnityContainer())
{
return container.LoadConfiguration();
}
}
Но этот код начинает генерировать исключение при разрешении зависимостей.
Может кто-то помочь мне с этим?
1 ответ
Это нарушение обычно связано с парой шаблонов кода, хотя для получения дополнительной информации вам следует обратиться к странице справки для CA2000.
- Фабричные методы
- Метод цепочки
- Отсутствует или неправильно обрабатывается исключение
Для чисто фабричных методов, в которых нет ничего неправильного, в некоторых случаях может быть достаточно просто переименовать метод. Я не знаю, какие префиксы ищет правило, но вы можете попробовать Construct
, Create
, New
, Build
(тот, который у вас есть).
Это, однако, не то, что не так с этим методом с точки зрения CA2000.
Итак, давайте посмотрим на рассматриваемый код:
var container = new UnityContainer().LoadConfiguration();
Здесь я собираюсь предположить, что LoadConfiguration
является методом, который возвращает тот же экземпляр, в котором он вызывается для цепочки методов, в свободном интерфейсе.
Другими словами, метод выглядит примерно так:
public class UnityContainer
{
public UnityContainer LoadConfiguration()
{
// load
return this;
}
}
Механизм анализа кода теперь видит этот код:
var temp = new UnityContainer();
var container = temp.LoadConfiguration();
return container;
Что случилось с temp
? Он не может обнаружить (см. Мою заметку ниже), что это тот же экземпляр, поэтому он думает, что вы потеряли temp
экземпляр здесь, и этим надо избавляться.
Хорошо, как насчет изменения кода на это:
var container = new UnityContainer();
container.LoadConfiguration();
return container;
Теперь я получаю еще одно нарушение из того же правила:
CA2000: В методе "Program.BuildContainer()" объект "контейнер" расположен не по всем путям исключений. Вызовите System.IDisposable.Dispose для объекта 'container' до того, как все ссылки на него выйдут из области видимости. ConsoleApplication31 C:\Dev\VS.NET\ConsoleApplication31\ConsoleApplication31\Program.cs 18 Active
По сути, механизм анализа кода теперь задается вопросом, что произойдет, если LoadConfiguration
выдает исключение, после чего вы будете терять объект временного контейнера, который никогда не был возвращен.
Итак, вот "исправленная" версия этого метода:
var container = new Container();
try
{
container.LoadConfiguration();
return container;
}
catch (Exception) // NOTE!
{
container.Dispose();
throw;
}
НОТА!: Обрабатывать только определенные исключения, которые вы знаете или думаете, что LoadConfiguration
может бросить, не справиться Exception
,
Примечание. Когда я говорю "не удается обнаружить" выше, это не означает, что в механизме анализа кода имеется код для обнаружения того, что либо дает сбой, либо имеет ошибку, это также может означать, что правило просто не делает это глубоко анализа, например, глядя на LoadConfiguration
метод и определение того, что он всегда возвращает this
,