Как Вы согласовываете IDisposable и МОК?

Если у вас есть объект типа T, например

T obj;

, то объявление

T *p = &obj;

инициализирует указатель p адресом памяти, занятым объект obj

выражение p + 1 указывает на память после объекта obj. Значение выражения p + 1 равно значению &obj plus sizeof( obj ), что эквивалентно

( T * )( ( char * )&obj + sizeof( obj ) )

Так что, если у вас есть массив, показанный в вашем посте int a[] = {0, 1, 2, 3};, вы можете переписать его объявление, используя typedef следующим образом:

typedef int T[4];

T a = { 0, 1, 2, 3 };

sizeof( T ) в этом случае равно sizeof( int[4] ) и, в свою очередь, равно 4 * sizeof( int )

Выражение &a дает адрес объем памяти, занимаемый массивом. Выражение &a + 1 дает адрес памяти после массива, а значение выражения равно &a + sizeof( int[4] )

С другой стороны, имя массива используется в выражениях - за редкими исключениями, например, использование имени массива в операторе sizeof - неявно преобразуется в указатель на его первый элемент.

Таким образом, выражение &a + 1 указывает на воображаемый элемент типа int[4] после реального первого элемента a. Выражение *(&a + 1) дает этот воображаемый элемент. Но поскольку элемент является массивом типа int[4], то это выражение преобразуется в указатель на свой первый элемент типа int *

. Этот первый элемент следует за последним элементом массива a. И в этом случае выражение *(&a + 1) - 1 дает адрес этого последнего элемента массива a

Разыменовывая в *(*(&a + 1) - 1), вы получаете значение последнего элемента массива a, поэтому будет выведено число 3.

41
задан Mr. Putty 12 June 2009 в 16:48
поделиться

6 ответов

AutoFac handles this by allowing the creation of a nested container. When the container is finished with, it automatically disposes of all IDisposable objects within it. More here.

.. As you resolve services, Autofac tracks disposable (IDisposable) components that are resolved. At the end of the unit of work, you dispose of the associated lifetime scope and Autofac will automatically clean up/dispose of the resolved services.

7
ответ дан 27 November 2019 в 00:55
поделиться

Я думаю, что в целом лучший подход - просто не утилизировать то, что было введено; вы должны предположить, что инжектор выполняет распределение и освобождение.

2
ответ дан 27 November 2019 в 00:55
поделиться

This depends on the DI framework. Some frameworks allow you to specify whether you want a shared instance (always using the same reference) for every dependency injected. In this case, you most likely do not want to dispose.

If you can specify that you want a unique instance injected, then you will want to dispose (since it was being constructed for you specifically). I'm not as familiar with Unity, though - you'd have to check the docs as to how to make this work there. It's part of the attribute with MEF and some others I've tried, though.

2
ответ дан 27 November 2019 в 00:55
поделиться

Вы определенно не хотите вызывать Dispose () для объекта, который был внедрен в ваш класс. Вы не можете сделать предположение, что вы единственный потребитель. Лучше всего поместить свой неуправляемый объект в какой-нибудь управляемый интерфейс:

public class ManagedFileReader : IManagedFileReader
{
    public string Read(string path)
    {
        using (StreamReader reader = File.OpenRead(path))
        {
            return reader.ReadToEnd();
        }
    }
}

Это просто пример, я бы использовал File.ReadAllText (path), если бы я пытался прочитать текстовый файл в строке.

Другой подход состоит в том, чтобы внедрить фабрику и самостоятельно управлять объектом:

public void DoSomething()
{
    using (var resourceThatShouldBeDisposed = injectedFactory.CreateResource())
    {
        // do something
    }
}
17
ответ дан 27 November 2019 в 00:55
поделиться

В фреймворке Unity есть два способа зарегистрировать внедренные классы: как одиночные (вы всегда получаете один и тот же экземпляр класса при его разрешении) или такой, как вы получаете новый экземпляр класса для каждого разрешения.

В последнем случае вы несете ответственность за удаление разрешенного экземпляра, если он вам не нужен (что является вполне разумным подходом). С другой стороны, когда вы удаляете контейнер (класс, который обрабатывает разрешения объектов), все одноэлементные объекты также автоматически удаляются.

Таким образом, очевидно, что нет проблем с внедренными одноразовыми объектами в среде Unity. Я не знаю других фреймворков, но полагаю, что, пока фреймворк внедрения зависимостей достаточно прочен, он наверняка так или иначе решает эту проблему.

1
ответ дан 27 November 2019 в 00:55
поделиться

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

Мой контейнер обычно живет в расширении IExtension, которое реализует интерфейс IServiceLocator. Это фасад для единства, и он обеспечивает легкий доступ в WCf сервисах. Плюс у меня есть доступ к событиям сервиса из ServiceHostBase.

Код, который вы получите в итоге, будет пытаться проверить, реализует ли любой зарегистрированный синглтон или любой созданный тип любой из интерфейсов, которые отслеживает фасад.

Это все еще не позволяет своевременно избавляться, поскольку вы привязаны к этим событиям, но это немного помогает.

Если вы хотите утилизировать своевременно (например, сейчас, а не после закрытия службы). Вам нужно знать, что полученный вами элемент является одноразовым, это часть бизнес-логики по его утилизации, поэтому IDisposable должен быть частью интерфейса объекта. И, вероятно, должна быть проверка ожиданий, связанных с вызовом метода dispose.

2
ответ дан 27 November 2019 в 00:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: