[英]Custom Attribute to cache read only Property value in C#
我正在尝试创建一个能够缓存属性值的自定义属性,该属性的类型是IWebElement
,创建起来有点昂贵,并且可能引发NoSuchElement
异常。
我已经取得了一些成功,像这样实现它:
protected Lazy<IWebElement> lazyWebElement;
protected virtual IWebElement cachedWebElement
{
get
{
if (!lazyWebElement.IsValueCreated)
{
try
{
lazyWebElement = new Lazy<IWebElement>(() => driver.FindElement(By.Id("someElement")),
LazyThreadSafetyMode.PublicationOnly);
}
catch (NoSuchElementException)
{
throw new NoSuchElementException("someElement is not present in DOM");
}
}
return lazyModal.Value;
}
}
而我想做的是
[CachedWebElement]
protected virtual IWebElement cachedWebElement => driver.FindElement(By.Id("someElement"));
但是Attribute
不允许在其构造函数中使用复杂类型,因此我无法将driver.FindElement(By.Id("someElement"))
作为参数传递。
如果我在派生的 class 中覆盖该属性,那么缓存它会很棒,因为现在我正在使用支持字段来保存值,并且整个机制都会丢失。
谢谢你。
你的方法可能不会很成功。 我的意思是,“只是添加一个属性”。
编译后和运行时,当您检索 object 时(即当您执行类似cachedWebElement.Displayed
的操作时),将调用get
方法。
构建项目时,所有属性都会get
附加到它们的set
访问器方法。 您可以在此处找到更多信息microsoft get keyword 。 基本上, { get; set; }
{ get; set; }
{ get; set; }
编译成函数,你不能真正“搞砸”。 它们是编译器的默认实现。 (如果我猜对了)。
如果您真的想遵循这种方法,请查看此答案。
现在,你的问题
FindElement()
之前检查它是否已经存在。我将假设您只想“缓存”有关元素的属性/信息,而不是实际与之交互。
然后,我们只需要创建一个“中间人”来处理每个元素的定位,但也会缓存我们找到的元素。 如果我们再次询问,class 将从 memory 将它们提供给我们,而不是“重新定位”它们。 让我们将它们作为扩展方法来做一些漂亮的事情:
public static class ElementLocator
{
private static readonly Dictionary<By, IWebElement> _CachedElements;
public static IWebElement FindElementFromCache(this IWebDriver driver, By by)
{
if (_CachedElements.ContainsKey(by))
return _CachedElements.Single(e => e.Key == by).Value;
return driver.FindElement(by);
}
public static ReadOnlyCollection<IWebElement> FindElementsFromCache(this IWebDriver driver, By by)
{
if (_CachedElements.ContainsKey(by))
{
List<IWebElement> foundCache = _CachedElements.Where(e => e.Key == by)
.Select(e => e.Value)
.ToList();
return new ReadOnlyCollection<IWebElement>(foundCache);
}
return driver.FindElements(by);
}
static ElementLocator()
{
_CachedElements = new Dictionary<By, IWebElement>();
}
}
然后,您可以简单地执行driver.FindElementFromCache(By.Id("someElement"));
但这可能不是完整的实现。 因为,在搜索多个元素时,可能添加了一个新元素。 一分钟前你得到了 4 个元素,现在添加了一个新的表格行,你有 5 个元素。 ElementLocator 将尝试查看缓存中是否有任何内容,将找到 4 个元素并将它们返回给您,而不搜索第 5 个元素。
IMO,创建缓存机制可能不是解决您问题的最佳方法。 它引入了(请原谅我的语言)你将面临的一大堆问题。
如果您可以向我们展示问题所在,我们可以找出可能不涉及缓存的问题。 我的意思是,不要说“我怎样才能更好地做这个缓存”或“我的缓存有问题”,但让我们看看为什么你需要一个缓存来开始元素。
祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.