通过构造函数注入的对象上的注册事件(PropertyChanged始终为null)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过构造函数注入的对象上的注册事件(PropertyChanged始终为null)相关的知识,希望对你有一定的参考价值。
是否可以通过构造函数注入一个对象并在其上注册一个事件?我目前正在尝试实现这样的功能,并且我的PropertyChanged
始终为null。我认为这与以下事实有关:我没有在我注册事件的类中实例化该对象,但我不太确定,因为我还是事件驱动代码的新手。
无论如何这里是相关代码:
通过依赖项注入:
public static class ServiceCollectionExtensions
{
public static void ConfigureWritable<T>(
this IServiceCollection services,
IConfigurationSection section,
string file = "appsettings.json") where T : class, new()
{
services.Configure<T>(section);
services.AddTransient<IWritableOptions<T>>(provider =>
{
var environment = provider.GetService<IHostingEnvironment>();
var options = provider.GetService<IOptionsMonitor<T>>();
return new WritableOptions<T>(environment, options, section.Key, file);
});
}
}
public interface IWritableOptions<out T> : IOptionsSnapshot<T> where T : class, new()
{
void Update(Action<T> applyChanges);
event PropertyChangedEventHandler PropertyChanged;
}
public class WritableOptions<T> : INotifyPropertyChanged, IWritableOptions<T> where T : class, new()
{
private readonly IHostingEnvironment _environment;
private readonly IOptionsMonitor<T> _options;
private readonly string _section;
private readonly string _file;
public WritableOptions(
IHostingEnvironment environment,
IOptionsMonitor<T> options,
string section,
string file)
{
_environment = environment;
_options = options;
_section = section;
_file = file;
}
public T Value
{
get
{
var fileProvider = _environment.ContentRootFileProvider;
var fileInfo = fileProvider.GetFileInfo(_file);
var physicalPath = fileInfo.PhysicalPath;
var jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(physicalPath));
var sectionObject = jObject.TryGetValue(_section, out JToken section) ?
JsonConvert.DeserializeObject<T>(section.ToString()) : (Value ?? new T());
return sectionObject;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public T Get(string name) => _options.Get(name);
public void Update(Action<T> applyChanges)
{
var fileProvider = _environment.ContentRootFileProvider;
var fileInfo = fileProvider.GetFileInfo(_file);
var physicalPath = fileInfo.PhysicalPath;
var jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(physicalPath));
var sectionObject = jObject.TryGetValue(_section, out JToken section) ?
JsonConvert.DeserializeObject<T>(section.ToString()) : (Value ?? new T());
applyChanges(sectionObject);
jObject[_section] = JObject.Parse(JsonConvert.SerializeObject(sectionObject));
File.WriteAllText(physicalPath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
OnPropertyChanged("Value");
}
}
使用注入依赖项的类:
public class ClientService : HostedService
{
public ClientService(IWritableOptions<ClientSettings> clients)
{
clients.PropertyChanged += PropertyChanged;
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
}
编辑:为了进一步阐明,我都在.Net Core WebAPI项目中使用了它。我这样注册ClientService:
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureWritable<ClientSettings>(Configuration.GetSection("ClientSettings"));
services.AddSingleton<IHostedService, ClientService>();
services.AddMvc();
}
然后我有了一个控制器,可以用来更新这些设置:
private IWritableOptions<ClientSettings> _clients;
public ClientController(IWritableOptions<ClientSettings> clients)
{
_clients = clients;
}
[HttpPost]
[Route(CoreConfigClientRoutes.UpdateRoute)]
public void UpdateClients([FromBody] IEnumerable<ModuleSetting> updatedClients)
{
var clients = _clients.Value.Clients.ToList();
foreach (var updatedClient in updatedClients)
{
var index = clients.IndexOf(clients.Where(c => c.Id == updatedClient.Id).First());
clients[index] = updatedClient;
}
_clients.Update(c => c.Clients = clients.ToArray());
}
来源:IHostedService,IWritableOptions
我在这里错过了什么吗?还是不可能?
正在运行的GitHub存储库:EventDI
答案
我正在WPF应用程序中超越。
如果您愿意,您可能不应该在下面使用代码。但是,为了快速进行“修补和继续”,我做了以下操作。
我放弃了上述解决方案,因为它因依赖项注入位而失败。只是手动描述了从何处获取appsettings.json
并删除了无法绑定组件的问题。
public class WritableOptions<T> : IWritableOptions<T> where T : class, new()
{
private readonly IOptionsMonitor<T> _options;
private readonly string _section;
public WritableOptions(
IOptionsMonitor<T> options,
string section,
string file)
{
_options = options;
_section = section;
}
public T Value => _options.CurrentValue;
public T Get(string name) => _options.Get(name);
public void Update(Action<T> applyChanges)
{
var physicalPath = Directory.GetParent(Environment.CurrentDirectory).Parent.Parent.FullName+ "\appsettings.json";
var jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(physicalPath));
var sectionObject = jObject.TryGetValue(_section, out JToken section) ?
JsonConvert.DeserializeObject<T>(section.ToString()) : (Value ?? new T());
applyChanges(sectionObject);
jObject[_section] = JObject.Parse(JsonConvert.SerializeObject(sectionObject));
File.SetAttributes(physicalPath, FileAttributes.Normal);
File.WriteAllText(physicalPath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
}
}
以上是关于通过构造函数注入的对象上的注册事件(PropertyChanged始终为null)的主要内容,如果未能解决你的问题,请参考以下文章
IOC 控制反转Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取要注入事件的 View 对象 | 通过反射获取 View 组件的事件设置方法 )