语法有助于访问泛型类和方法中的属性



我有一个类AppGeneralSettings,我用它来保存和加载设置,它序列化和反序列化为文件。

我想截获保存和加载方法,以便我可以加密/解密密码,使其不以明文形式保存。这个问题更多的是关于访问任何对象,而不是关于加密/解密或密码。

我在访问通用对象以能够更改它们的语法时遇到问题。例如,以下内容不起作用并给出错误

this.SettingsDict.First().Value.EmailPassword = EncryptPassword(this.SettingsDict.First().Value.EmailPassword);

(AppGeneralSettings<T>)this.SettingsDict.First().Value.EmailPassword = EncryptPassword((AppGeneralSettings<T>)this.SettingsDict.First().Value.EmailPassword);

给出错误

'AppGeneralSettings<T>' does not contain a definition for 'SettingsDict' and no accessible extension method 'SettingsDict' accepting a first argument of type 'AppGeneralSettings<T>' could be found (are you missing a using directive or an assembly reference?)

如何在这两种方法中序列化和反序列化属性之前访问 Save 和 Load 方法中的"this"和"t"对象以更改属性?

保存和加载方法:

public void Save(string fileName = DEFAULT_FILENAME)
{
string filepath = GetFullFilePath(fileName);
// Encrypt EmailPassword
//this.SettingsDict.First().Value.EmailPassword = EncryptPassword(this.SettingsDict.First().Value.EmailPassword);
File.WriteAllText(filepath, JsonConvert.SerializeObject(this));
}
public static T Load(string fileName = DEFAULT_FILENAME)
{
string filepath = GetFullFilePath(fileName);
T t = new T();
if (File.Exists(filepath))
{
t = JsonConvert.DeserializeObject<T>(File.ReadAllText(filepath));
// Decrypt EmailPassword
// t.SettingsDict.First().Value.EmailPassword = DecryptPassword(t.SettingsDict.First().Value.EmailPassword);
}
return t;
}

全班:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp
{
public class GeneralSettings
{
public string EmailUsername { get; set; }
public string EmailPassword { get; set; }
public int EmailPort { get; set; }
public string EmailHost { get; set; }
public bool EmailSSL { get; set; }
}
public class UserGeneralSettings : AppGeneralSettings<UserGeneralSettings>
{
public Dictionary<string, GeneralSettings> SettingsDict = new Dictionary<string, GeneralSettings>();
}
public class AppGeneralSettings<T> where T : new()
{
private const string settingFolderPath = @"SomeAppData";
private const string DEFAULT_FILENAME = "GeneralSettings.jsn";
private const string cipherPW = "randompw";
public void Save(string fileName = DEFAULT_FILENAME)
{
string filepath = GetFullFilePath(fileName);
// Encrypt EmailPassword
//this.SettingsDict.First().Value.EmailPassword = EncryptPassword(this.SettingsDict.First().Value.EmailPassword);
File.WriteAllText(filepath, JsonConvert.SerializeObject(this));
}
public static T Load(string fileName = DEFAULT_FILENAME)
{
string filepath = GetFullFilePath(fileName);
T t = new T();
if (File.Exists(filepath))
{
t = JsonConvert.DeserializeObject<T>(File.ReadAllText(filepath));
// Decrypt EmailPassword
// t.SettingsDict.First().Value.EmailPassword = DecryptPassword(t.SettingsDict.First().Value.EmailPassword);
}
return t;
}
private static string GetFullFilePath(string fileName = DEFAULT_FILENAME)
{
string dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string path = Path.Combine(dir, settingFolderPath);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return Path.Combine(path, fileName);
}
private string EncryptPassword(string plaintext)
{
if (string.IsNullOrEmpty(plaintext))
{
return string.Empty;
}
else
{
return StringCipher.Encrypt(plaintext, cipherPW);
}
}
private string DecryptPassword(string encryptedtext)
{
if (string.IsNullOrEmpty(encryptedtext))
{
return string.Empty;
}
else
{
return StringCipher.Decrypt(encryptedtext, cipherPW);
}
}
}
}

SettingsDict是在子类UserGeneralSettings中定义的,因此您无法使用this从父类访问它。

您也不能通过T访问SettingsDict,因为它可以引用任何具有无参数构造函数的类型。

为了能够访问SettingsDict需要将T限制为包含该属性的类型。一种方法是为所有子类创建一个接口,例如:

public interface IGeneralSettings
{
Dictionary<string, GeneralSettings> SettingsDict { get; }
}
public class UserGeneralSettings : AppGeneralSettings<UserGeneralSettings>, IGeneralSettings
{
public Dictionary<string, GeneralSettings> SettingsDict { get; private set; } = new Dictionary<string, GeneralSettings>();
}

然后你可以约束你的AppGeneralSettings<T>

public class AppGeneralSettings<T> where T : IGeneralSettings, new()

这将允许:

t.SettingsDict.First().Value.EmailPassword = DecryptPassword(t.SettingsDict.First().Value.EmailPassword);

最新更新