Получить уведомление об удалении / уничтожении объекта
Мне нужен способ для отслеживания экземпляров различных классов, без каких-либо знаний о том, что они отслеживаются. По сути, у меня есть фабрика классов, которая создает экземпляры и передает их другому потоку. Как только этот поток завершает и выгружает экземпляр, мне нужно получить уведомление об этом, чтобы я мог выполнить подсчет ссылок и выйти из фабрики классов, когда все экземпляры исчезли.
Проблема в том, что я не могу изменить ни один из классов, которые я буду загружать, потому что я не контролирую их исходный код.
Отслеживать экземпляры, которые я создаю, очень просто, я могу просто поместить их в какую-то коллекцию по мере их создания. Отслеживание их уничтожения вызывает у меня проблемы. Если бы я мог изменить исходный код, я бы добавил событие в каждый класс, а когда я создаю экземпляр, я бы подключился к событию и использовал его в качестве своего уведомления. Но я не могу этого сделать.
Итак, вопрос заключается в следующем: существует ли хитрый способ контролировать экземпляр объекта и определять, когда он уничтожается?
4 ответа
Нет способа получить активное уведомление, но вы можете сохранить WeakReference
на объекты и периодически проверять, если кто-либо умер.
Изменить: мне нравится ответ Рид лучше, чем мой!
Поскольку вы создаете объекты, кажется, что вы можете вернуть Decorator вместо фактического экземпляра.
Используя Pattern Decorator Pattern, вы можете "обернуть" возвращаемый объект в свой собственный, оформленный API. Украшение может предоставить IDisposable реализацию, которая предоставила ваше уведомление об уничтожении.
Если вы удерживаете список ссылок на созданные вами экземпляры, они не будут собирать мусор и поэтому никогда не будут уничтожены...
Вместо этого вы можете создать репозиторий, содержащий список Guids и создать новый Guid для каждого экземпляра, а затем добавить его в список - что-то вроде FactoryRepository. Таким образом, у вас нет проблем с ссылками для сборки мусора, поскольку Guids - это структуры, а не ссылочные типы. Затем вы можете наследовать от каждого класса, чтобы создать тип, который может уведомлять об уничтожении. Я предполагаю, что, поскольку вы не можете изменить код исходных классов, вы также не можете изменить потребителей этих классов, поэтому что-то вроде шаблона декоратора (через интерфейс) отсутствует, потому что типы не будут совместимы.
Очень упрощенный пример:
public class OriginalClassDestroyNotifier : OriginalClass
{
private readonly Guid _instanceId;
public OriginalClassDestroyNotifier(Guid instanceId)
{
_instanceId = instanceId;
}
~OriginalClassDestroyNotifier()
{
FactoryRepository.NotifyDestroyed(_instanceId);
}
}
Как насчет того, чтобы контролировать разрушение объекта:
public void Destroy(T obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
if (!_living.Contains(obj))
throw new ArgumentException("Where did this obj come from?");
using (obj as IDisposable)
{
}
_living.Remove(obj); // List?
}