Из вашего фрагмента у вас есть:
- Реализация
ISerialPortController
с именем SerialPortController
, которая зарегистрирована в приложении как отдельный экземпляр .Это означает, что он будет существовать в течение срока службы контейнера Autofac, который также обычно является жизненным циклом приложения. - Значение, которое использует
SerialPortController
, происходит от ISettingsModel
.Настройки в этой модели могут меняться в течение всего приложения, и когда они это сделают, SerialPortController
необходимо начать использовать новое значение.
Я начну с ответа на простой вопрос: Невозможно повторно инициализировать синглтон в Autofac. Преимущества и недостатки синглтона в том, что ... это синглтон.Как только это построено, это построено.Вы должны отбросить весь контейнер и перестроить его, чтобы заставить синглтон перестраиваться.
Существуют и другие способы решения проблемы , но для этого не требуется на самом деле повторной инициализации синглтона.
Вариант 1. Не делайте контроллер одиночным
Вместо того, чтобы делать контроллер одиночным, сделайте его InstancePerDependency
.Используемые настройки сохраняются только до тех пор, пока отдельный экземпляр жив.
Могут быть причины, по которым вы хотите, чтобы это был одноэлементный файл, например, может быть, это дорого создавать или может действовать как пул ресурсов иличто-то.Это круто, есть больше вариантов.Это просто самый простой ответ.
Вариант 2: Изменить параметр порта на что-то более динамичное
Что я имею в виду, вместо того, чтобы SerialPortController
принимал буквальный номер порта,для этого потребуется функция , которая используется для получения номера порта.
Например, скажем, ISettingsModel
автоматически всегда имеет последнее значение.Если вы просите синглтон ISettingsModel
для ConveyorSerialPort
, то всегда самое последнее.Вместо этого вы могли бы изменить контроллер на ISettingsModel
.
public class SerialPortController
{
private readonly ISettingsModel _model;
public SerialPortController(ISettingsModel model)
{
this._model = model;
}
public void DoSomething()
{
// port will always be up to date.
var port = this._model.ConveyorSerialPort;
this.CommunicateOn(port);
}
}
В этом случае, до ISettingsModel
можно сохранить свежие значения, но пока это происходит, контроллер может бытьсинглтон (и, в идеале, может ISettingsModel
, иначе у вас будет ситуация зависимости в неволе .
Но, скажем, ISettingsModel
генерируется каждый раз, когда разрешается.чтобы получить новые настройки, вы должны получить новый ISettingsModel
. Это нормально, вы можете сделать это и с Autofac, используя Func<T>
:
public class SerialPortController
{
private readonly Func<ISettingsModel> _modelFactory;
public SerialPortController(Func<ISettingsModel> modelFactory)
{
this._modelFactory = modelFactory;
}
public void DoSomething()
{
// port will always be up to date.
var port = this._modelFactory().ConveyorSerialPort;
this.CommunicateOn(port);
}
}
Автоматически сгенерированный Func<ISettingsModel>
восстановитновый ISettingsModel
из контейнера. Так как ваш контроллер является одноэлементным, он будет исходить из корня контейнера. Будьте осторожны, если ISettingsModel
одноразовый. Если он одноразовый (IDisposable
), тоAutofac будет удерживать его до тех пор, пока контейнер не будет удален, что приведет к утечке памяти. Есть и способы обойти это тоже. , но это может начать усложняться, и я хочу получить вам полезный ответ.Документация естьдовольно хорошо (если я сам так говорю) и есть много примеров.Это долго, но стоит потратить время на проверку.