Обнаружение и добавление недостающих свойств в конфигурации JSON.C#

Место общения программистов C#
Ответить
Anonymous
 Обнаружение и добавление недостающих свойств в конфигурации JSON.

Сообщение Anonymous »

Я хочу иметь класс в библиотеке классов, который динамически создает файл settings.json из объекта T, и если T изменяется, добавляются или удаляются свойства. Я написал этот класс, который отлично подходит для создания файла JSON:

Код: Выделить всё

using Microsoft.Extensions.Options;
using System.Reflection;
using System.Text.Json;

namespace Common.Settings
{
public static class Settings
{
public static string FilePath { get; private set; }
public static string FileName { get; private set; }

public static T UseSettings(this IServiceCollection services, Action? configureOptions) where T : class, new()
{
var options = new Options();
configureOptions?.Invoke(options);

FilePath = options.Path;
FileName = options.FileName;
var filePath = Path.Combine(options.Path, options.FileName);

// Check if the JSON file exists
if (!File.Exists(filePath))
{
// Create the directory if it doesn't exist
Directory.CreateDirectory(options.Path);

// Create a new instance of type T with initialized nested properties
var settings = CreateDefaultSettings();

// Serialize the default settings
var defaultSettings = JsonSerializer.Serialize(settings);

// Write the default settings to the JSON file
File.WriteAllText(filePath, defaultSettings);
}

// Read the JSON file
var json = File.ReadAllText(filePath);

// Deserialize the JSON into a JObject
var rootElement = JsonDocument.Parse(json).RootElement;

// Get properties of type T
var properties = typeof(T).GetProperties();

// Flag to indicate if any property mismatch found
var mismatchFound = false;

foreach (var property in properties)
{
// Check if property exists in the JSON object
if (!rootElement.TryGetProperty(property.Name, out var propertyElement))
{
mismatchFound = true;
Console.WriteLine($"Property '{property.Name}' not found in {options.FileName}");
rootElement = UpdateJsonObject(rootElement, filePath);
continue; // Skip to next property
}

}

if (mismatchFound)
{
// Handle property mismatch (e.g., update JSON, log a warning)
//Console.WriteLine($"** Property mismatches found in {options.FileName} JSON configuration. Consider updating the {options.FileName} file or handling the mismatches in your application. **");
Console.WriteLine($"** Property mismatches found in {options.FileName} JSON configuration. The missing properties were added to {options.FileName}.  **");
}

// Deserialize the JSON into an instance of type T
var deserializedSettings = JsonSerializer.Deserialize(json);

// Register an instance of the Settings class with the deserialized values
services.AddSingleton(deserializedSettings);
return deserializedSettings;
}

private static T CreateDefaultSettings() where T : class, new()
{
var settings = new T();
var properties = typeof(T).GetProperties();

foreach (var property in properties)
{
if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
{
var nestedSettings = typeof(Settings).GetMethod("CreateDefaultSettings", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(property.PropertyType)
.Invoke(null, null);

property.SetValue(settings, nestedSettings);
}
}

return settings;
}

private static JsonElement UpdateJsonObject(JsonElement element, string filePath) where T : class, new()
{
var settings = new T();
var properties = typeof(T).GetProperties();

foreach (var property in properties)
{
Console.WriteLine(property);
if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
{
var nestedSettings = typeof(Settings).GetMethod("UpdateJsonObject", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(property.PropertyType)
.Invoke(null, [element, filePath]);

if (element.TryGetProperty(property.Name, out var ele))
{
property.SetValue(settings, ele);
}
else
{
property.SetValue(settings, nestedSettings);
}

}
}
var defaultSettings = JsonSerializer.Serialize(settings);

// Write the default settings to the JSON file
File.WriteAllText(filePath, defaultSettings);
return JsonDocument.Parse(defaultSettings).RootElement;
}

}

public class Options
{
public string Path { get; set; } = "config";
public string FileName { get; set; } = "settings.json";

}
}
При изменении T я сталкиваюсь со следующей ошибкой, с которой не могу разобраться:

Код: Выделить всё

System.ArgumentException: 'Object of type 'System.Text.Json.JsonElement' cannot be converted to type 'Common.Settings.JWTSecuritySettings'.'
Ошибка касается вложенного класса в T, как показано здесь:

Код: Выделить всё

  public class AppSettings{
public string Servicename { get; set; }
public string AppDomain { get; set; }

public JWTSecuritySettings JWTSettings { get; set; }

public DBConnectionSettings DBSettings { get; set; }

public string TenantDBEncryptionKey { get; set; }
}

public class JWTSecuritySettings
{
public string PrivateKey { get; set; }
public string PublicKey { get; set; }
public string Issuer { get; set; } = "http://localhost:5001";
}

public class DBConnectionSettings
{
public string ConnectionString { get; set; }
="Host=localhost;Database=DEVDB;Username=postgres;Password=post";
public string DBName { get; set; }
}
Я пытался удалить оператор if и использовать только раздел else, но это ничего не дало, просто выдало еще одну ошибку

Подробнее здесь: https://stackoverflow.com/questions/790 ... son-config
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»