У меня есть помощник-класс для моих юнит-тестов, которые разделяют ссылку на COM-объект в памяти:COM-объект был выпущен непреднамеренно
public class UnitTestGeometryProvider
{
public static readonly IGeometry Geometry = Deserialize();
}
Геометрия десериализации из XML-файла, который хранится в качестве файла ресурсов и прилагается к проекту. После этого он обернут в COM-объект:
public static IGeometry Deserialize()
{
return (IGeometry) new XMLSerializerClass().LoadFromString(myXDoc.OuterXml, null, null);
}
Теперь у меня есть два тест-метода, которые используют геометрию, хранящуюся в этом классе:
[TestClass()]
public class MyTest
{
[TestMethod()]
public void FirstTest()
{
var p = UnitTestGeometryProvider.Geometry;
}
[TestMethod()]
public void SecondTest()
{
var p = UnitTestGeometryProvider.Geometry;
}
}
При запуске второго я получаю COMException:
COM-объект, который был отделен от его основного RCW не может быть использован
Интересно, почему ссылка на COM-объект выпущена, поскольку она помечена static
в UnitTestGeometryProvider
, и я не могу ее явно освободить. Таким образом, даже , еслиуправляемый ресурс экземпляр выйдет за пределы области видимости (который не является статическим), базовый COM-объект должен уйти только тогда, когда все мои тесты закончены или более общие, когда приложение завершается, или мне что-то не хватает?
Я использую ArcObjects и Visual NUnit.
Инициализация * статического поля с COM-объектом - довольно плохая идея и работает только случайно. У вас нет гарантии, что это произойдет в нужное время и в правильной нити. Что важно * многопользовательские, COM-объекты с резьбой, принадлежащие квартире, принадлежат определенному потоку, и если этот поток заканчивается, то объект мертв как дорнига. Вместо этого используйте свойство, вызывайте Deserialize(), если объект по-прежнему равен нулю. –
@ HansPassant Ну, разве это тест, приведенный выше однопоточного теста? Здесь не задействована многопоточность, или же «статический» подразумевает ее собственный? – HimBromBeere
Такая переменная получает свое значение от инициализатора типа (aka static constructor). .NET дает очень мало гарантий того, когда и как они работают, только для того, чтобы они работали достаточно рано. У вас есть тестовый бегун, у которого вполне может быть своя идея, как он инициализирует все, прежде чем запускает тест.Если вы хотите получить гарантию, что это никогда не пойдет не так, вы не сможете ее получить, у вас есть очень сильное доказательство того, что оно ошибочно. –