我试图找出将锁定应用于以下类的正确方法。简而言之,该对象是一个单例,创建时,从给定目录中的xml文件构建可变数目的菜单。现在,只允许读取,因此不发生锁定(MSDN状态读取从字典中是线程安全的)。但是,我还连接了一个文件系统观察器,以便在发生更改时重新构建菜单。有两个字典发生读取,所以我需要一种方法来处理这个问题。我可以使用Lock(this),但有没有更好的方法?所以,我想冻结读取的唯一时间是更新发生的时间(查看ctor)。何处以及如何应用锁
下面是一个视觉的类:
public class XmlMenuProvider : IMenuProvider {
private readonly INavigationService navigation;
private readonly Dictionary<string, IEnumerable<MenuItem>> menus;
private readonly Dictionary<string, Dictionary<string, MenuItem>> menusLookup;
private readonly FileSystemWatcher monitor;
public XmlMenuProvider(string folderPath, INavigationService navigation)
{
this.navigation = navigation;
this.menusLookup = new Dictionary<string, Dictionary<string, MenuItem>>();
this.menus = LoadFromSourceDirectory(folderPath);
this.monitor.Changed += (o, e) => {
// TODO - Add Locking
};
}
public IEnumerable<MenuItem> GetMenuItems(string name) {
return menus[name];
}
public MenuItem FindItemByName(string menu, string name) {
return menusLookup[menu][name];
}
private Dictionary<string, IEnumerable<MenuItem>> LoadFromSourceDirectory(string folderPath) {
var menus = new Dictionary<string, IEnumerable<MenuItem>>();
foreach (var file in Directory.GetFiles(folderPath, "*.xml")) {
var root = XDocument.Load(file).Elements().First();
var name = root.Attribute("name").Value;
var lookup = new Dictionary<string, MenuItem>();
menusLookup.Add(name, lookup);
menus.Add(name, BuildMenuHiearchyFromElement(root, lookup, null));
}
return menus;
}
private IEnumerable<MenuItem> BuildMenuHiearchyFromElement(XElement element, Dictionary<string, MenuItem> lookup, MenuItem parent) {
return element.Elements("Item")
.Select(e => {
var mi = CreateMenuItemFromElement(e, lookup, parent);
lookup.Add(mi.Name, mi);
return mi;
}
).ToList();
}
private MenuItem CreateMenuItemFromElement(XElement element, Dictionary<string, MenuItem> lookup, MenuItem parent) {
var name = element.Attribute("Name").Value;
var display = element.Attribute("DisplayName").Value;
var isClickable = true;
var roles = element.Attribute("Roles").Value.Split(',');
if (roles.Length == 1 && roles.First() == string.Empty) {
roles = new string[] { };
}
var attrClick = element.Attribute("IsClickable");
if (attrClick != null) {
isClickable = bool.Parse(attrClick.Value);
}
var navigateUrl = string.Empty;
if (isClickable) {
navigateUrl = navigation.FetchDestination(name);
}
return new MenuItem(name, display, navigateUrl, isClickable, roles, x => BuildMenuHiearchyFromElement(element, lookup, x), parent);
}
}
谢谢。
是的,但后来我还需要锁定执行读取的两个方法否?这正是我重新构建菜单时只想锁定的位置。锁定(这)将解决这个问题。 – Marco 2011-03-08 14:51:59
@Marco - 您不会锁定* lock()中提到的*实例,您可以锁定实例。巨大差距。 @Felice - 为什么从不“锁定(this)”? – 2011-03-08 14:54:24
当你保护一个静态的时候''lock'应该是静态的,而当你保护一个实例时''lock应该是静态的。 – 2011-03-08 14:55:33