Сериализация словаря в XML C#
У меня есть словарь, в котором я должен добавить объект, когда пользователь входит в систему, и мне нужно удалить объект, когда пользователь выходит из системы в Windows. Я также сериализую словарь в XML. Поскольку я новичок в C#, а также служба Windows, у меня есть некоторые сомнения.
Вот мой код
public class UserSessionCapturePlugin : IInformServiceHandler
{
public Dictionary<int, UserSessionInfo> UserSessionLookupTable = new Dictionary<int, UserSessionInfo>();
public void OnSessionChange(SessionChangeDescription changeDescription)
{
switch (changeDescription.Reason)
{
//Case of Logon
case SessionChangeReason.SessionLogon:
//CreateRunningProcessesLog("UserSession-SessionLogon");
UserSession userSessionLogin = new UserSession()
{
UserName = MachineHelper.GetUsername(),
UserGuid = MachineHelper.GetUserGuid(),
MachineGuid = MachineHelper.GetMachineGUID(),
LoginTime = DateTime.Now.ToUniversalTime(),
SessionGuid = Guid.NewGuid(), //New Guid generated for tracking the UserSession, this will be created on on logon
IsReadable = false,
SessionId = changeDescription.SessionId,
};
UserSessionInfo userSessionInfoLogin = new UserSessionInfo()
{
UserName = MachineHelper.GetUsername(),
SessionGuid = userSessionLogin.SessionGuid,
IsActiveUser = true,
SessionId = changeDescription.SessionId,
LoginTime = userSessionLogin.LoginTime,
State = RowState.Added,
};
UserSessionLookupTable.Add(userSessionInfoLogin.SessionId, userSessionInfoLogin);
XmlSerializer serializer = new XmlSerializer(typeof(Dictionary<Guid, UserSessionInfo>));
TextWriter textWriter = new StreamWriter(@"UserSessionLookupDictionarySerialized.xml");
serializer.Serialize(textWriter, UserSessionLookupTable);
textWriter.Close();
//Case of Logoff
case SessionChangeReason.SessionLogoff:
UserSession userSessionLogoff = new UserSession()
{
UserName = MachineHelper.GetUsername(),
UserGuid = MachineHelper.GetUserGuid(),
MachineGuid = MachineHelper.GetMachineGUID(),
LogOffTime = DateTime.Now.ToUniversalTime(),
IsReadable = true,
SessionId = changeDescription.SessionId,
};
UserSessionLookupTable.Remove(userSessionLogoff.SessionId);
XmlSerializer serializer = new XmlSerializer(typeof(Dictionary<Guid, UserSessionInfo>));
TextWriter textWriter = new StreamWriter(@"UserSessionLookupDictionarySerialized.xml");
serializer.Serialize(textWriter, UserSessionLookupTable);
textWriter.Close();
break;
}
}
}
Но у меня есть следующие сомнения
Если несколько пользователей входят в систему, будет ли этот xml заменен данными о последнем входе в систему или будет добавлена дополнительная запись о новом пользователе?
При выходе из системы будут ли удаляться пользовательские данные из xml или же нужны какие-либо другие методы (например, десериализация и удаление записи)?
В настоящее время я не могу отладить или запустить код, поэтому я публикую его здесь.
1 ответ
Как UserSessionLookupTable
является нестатичным объектом, поэтому срок его службы зависит от продолжительности жизни родителя. Пока вы используете один и тот же экземпляр UserSessionCapturePlugin
для всех пользователей будет храниться запись всех пользователей.
Если вы создаете другой экземпляр UserSessionLookupTable
за каждый запрос, который будет содержать только запись последнего пользователя.
Также XmlSerializer
не может сериализовать словарь напрямую.
Чтобы исправить поведение и вести учет всех пользовательских сеансов, я предлагаю изменить способ сохранения информации о сеансах.
- Перед сохранением информации о новом сеансе пользователя сначала загрузите и десериализуйте существующий XML, добавьте в него новую запись, снова сериализуйте и сохраните в файл. (Вы должны убедиться, что если это первый раз, файл не будет существовать, так что обработайте это)
- Перед удалением информации о сеансе пользователя сначала загрузите и десериализуйте существующий xml, удалите запись, которую вы хотите удалить, снова сериализуйте и сохраните ее обратно в файл.
Вот небольшой фрагмент
Dictionary<Guid, UserSessionInfo> LoadUserSessionData()
{
try
{
var serializer = new XmlSerializer(typeof(KeyValuePair<Guid, UserSessionInfo>[]));
using (var stream = new FileStream(@"UserSessionLookupDictionarySerialized.xml", FileMode.Open))
{
var sessionData = (KeyValuePair<Guid, UserSessionInfo>[])serializer.Deserialize(stream)
return sessionData.ToDictionary(i => i.Key, i => i.Value);
}
}
catch (FileNotFoundException)
{
return new Dictionary<int, UserSessionInfo>();
}
}
void SaveUserSessionData(Dictionary<Guid, UserSessionInfo> sessionData)
{
var serializer = new XmlSerializer(typeof(KeyValuePair<Guid, UserSessionInfo>[]));
using (var stream = new FileStream(@"UserSessionLookupDictionarySerialized.xml", FileMode. OpenOrCreate))
{
serializer.Serialize(stream, sessionData.ToArray());
}
}
После этого OnSessionChange
будет выглядеть так
public void OnSessionChange(SessionChangeDescription changeDescription)
{
switch (changeDescription.Reason)
{
//Case of Logon
case SessionChangeReason.SessionLogon:
//CreateRunningProcessesLog("UserSession-SessionLogon");
UserSession userSessionLogin = new UserSession()
{
UserName = MachineHelper.GetUsername(),
UserGuid = MachineHelper.GetUserGuid(),
MachineGuid = MachineHelper.GetMachineGUID(),
LoginTime = DateTime.Now.ToUniversalTime(),
SessionGuid = Guid.NewGuid(), //New Guid generated for tracking the UserSession, this will be created on on logon
IsReadable = false,
SessionId = changeDescription.SessionId,
};
UserSessionInfo userSessionInfoLogin = new UserSessionInfo()
{
UserName = MachineHelper.GetUsername(),
SessionGuid = userSessionLogin.SessionGuid,
IsActiveUser = true,
SessionId = changeDescription.SessionId,
LoginTime = userSessionLogin.LoginTime,
State = RowState.Added,
};
var userSessionLookupTable = LoadUserSessionData();
userSessionLookupTable.Add(userSessionInfoLogin.SessionId, userSessionInfoLogin);
SaveUserSessionData(userSessionLookupTable);
break;
//Case of Logoff
case SessionChangeReason.SessionLogoff:
UserSession userSessionLogoff = new UserSession()
{
UserName = MachineHelper.GetUsername(),
UserGuid = MachineHelper.GetUserGuid(),
MachineGuid = MachineHelper.GetMachineGUID(),
LogOffTime = DateTime.Now.ToUniversalTime(),
IsReadable = true,
SessionId = changeDescription.SessionId,
};
var userSessionLookupTable = LoadUserSessionData();
userSessionLookupTable.Remove(userSessionLogoff.SessionId);
SaveUserSessionData(userSessionLookupTable);
break;
}
}