Custom Attribute to cache read only Property value in C# - c#

I am trying to create a Custom Attribute capable of caching the value of a property, the type of the property is IWebElement which is somewhat expensive to create and could throw a NoSuchElement exception.
I have had some success implementing it like this:
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;
}
}
And what I would like to do is
[CachedWebElement]
protected virtual IWebElement cachedWebElement => driver.FindElement(By.Id("someElement"));
But Attribute does not allow complex types in it's constructor so I am not able to pass driver.FindElement(By.Id("someElement")) as a parameter.
Having it cached would be great as right now I am using a backing field to save the value and the whole mechanism is lost if I override the property in a derived class.
Thank you.

You probably won't be very successful in your approach. I mean, "just adding an attribute".
After compiling, and during runtime, when you retrieve your object (i.e. when you do something like cachedWebElement.Displayed), a get method is called.
When a project is build, all properties get get set accessor methods attached to them. You can find out more here microsoft get keyword. Basically, the { get; set; } get compiled into functions, that you can't really "mess" with. They are the default implementations of the compiler. (if I got that right).
If you really want to follow this approach, take a look at this answer.
Now, to your problem
If you want to have a "cache" for the elements properties, that's fine. You can create a class that will hold your elements for you, and before each FindElement() will check to see if it already exists.
If you also want to be able to "click" an element, that's impossible. If you "FindElement" on a button, and then the page changes, and you want to Click() it from cache, that can't happen. The page changed. There is a reason that exception is thrown.
I will assume that you want to "cache" only the properties/information about the element, and not actually interact with it.
Then, we will just have to create a "middle man" that will handle locating each element, but will also cache the elements we find. If we ask them again, the class will give them to us from memory instead of "re-locating" them. Let's do them as extension methods to be a little pretty:
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>();
}
}
Then, you can simply do driver.FindElementFromCache(By.Id("someElement"));
But this might not be the complete implementation. Because, when searching for multiple elements, maybe a new one was added. Instead of 4 elements you got a minute ago, now a new table row is added, and you have 5 elements. The ElementLocator will try to see if there is anything in cache, will find 4 elements and return them to you without searching for the 5th one.
IMO, creating a caching mechanism MIGHT not be the best solution to your problem. It introduces (excuse my language) a shit-ton of problems that you will face down the road.
If you could present us with what the problem is, we could figure out something that might not involve caching. I mean, don't say "how can I do this cache better" or "my caching has a problem", but let's see why you need a cache for elements to begin with.
Best of luck to you!

Related

How do you use selenium ExpectedConditions in a page object model design?

Hopefully I'm not the first person to encounter this issue.
I'm writing some selenium tests in C# and have a dilemma when trying to adobt a page object model design whilst also needing to do some explicit waits with the ExpectedConditions class.
Let's say I'm storing my elements in an element map class that is simply a property that calls the .FindElement method using an XPath stored in a resources file...
public class PageObject {
public IWebElement Element
{
get { return DriverContext.Driver.FindElement(By.XPath(Resources.Element)); }
}
}
Then I would go on to use that property in various selenium methods.
The issue I have is I also need to check whether this element is visible on the page, and it will error before I can perform the checked (e.g. with WebDriverWait, passing in ExpectedConditions.ElementIsVisible(by) to the .until method).
How do I cleanly seperate out the IWebElement and By locator and allow for this explicit wait/check where needed?
TLDR - How do I maintain a Page Object Model design whilst also having the flexibility to use explicit waits based on the By locator of my elements.
Many thanks,
I use page objects all the time but I have locators at the top of the class instead of elements. I then use the locators to click buttons, etc. as needed. The advantage of this is I only access the element on the page when needed which avoids stale element exceptions, etc. See a simple example below.
class SamplePage
{
public IWebDriver Driver;
private By waitForLocator = By.Id("sampleId");
// please put the variable declarations in alphabetical order
private By sampleElementLocator = By.Id("sampleId");
public SamplePage(IWebDriver webDriver)
{
this.Driver = webDriver;
// wait for page to finish loading
new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(waitForLocator));
// see if we're on the right page
if (!Driver.Url.Contains("samplePage.jsp"))
{
throw new InvalidOperationException("This is not the Sample page. Current URL: " + Driver.Url);
}
}
public void ClickSampleElement()
{
Driver.FindElement(sampleElementLocator).Click();
}
}
I would recommend against storing locators in a separate file because it breaks one of the mantras of page object model which is everything to do with the page goes in the page object. You shouldn't have to open anything but one file to do anything with Page X, the page object class.

How to add backing variable for property with ReSharper

I have created property from code with ReSharper (moved from some method that was too long):
private static SomeFunctions XmlSomeFunctions
{
get
{
// some logic
return someFunctions;
}
}
However, I want it to be something like this:
private static SomeFunctions xmlSomeFunctions;
private static SomeFunctions XmlSomeFunctions
{
get
{
if (xmlSomeFunctions == null)
{
// some logic
xmlSomeFunctions = someFunctions;
}
return xmlSomeFunctions;
}
}
But I have not found any entry in context menu (Ctrl+Shift+R = Refactor This) in ReSharper that could help me with this task. Is there any way I can create above code automatically with ReSharper?
If I won't rewrite this code (manually for now, preferably with ReSharper, if I know how), I will have that logic executed many times (instead of once) if I ask for XmlSomeFunctions in different places in my code.
What your actually trying to do is create a lazily instantiated property. A better way to do this is just use the Lazy class in .Net. Reuse this class instead of trying to automate the repetitive code with resharper would be my advice.
See http://msdn.microsoft.com/en-us/library/dd642331(v=vs.110).aspx
You do have this possibility. Place your cursor on the name of the property (XmlSomeFunctions) and click on the hammer icon to the left.
You'll have to add the if statement yourself though.

Code Contracts and failure on private static readonly fields

I have a private static readonly field in my class:
public class MyClass
{
// ISSUE #1 -- requires unproven: path != null
private static readonly DirectoryInfo MyDirectory =
new DirectoryInfo(Settings.Default.MyDirectoryPath);
protected virtual void SomeMethod()
{
if (MyDirectory.Exists)
{
// ISSUE #2 -- requires unproven: !string.IsNullOrEmpty(path)
var catalog = new DirectoryCatalog(MyDirectory.FullName);
}
}
}
For issue #1 I used a null coalescing operator to default to some magic string and that fixed it, but I don't really like that solution. I was hoping there was a better solution.
For issue #2 the only thing I can think of is using a Contract.Assumes because if I attempt to use Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName)); it complains about visibility (private field used in a requires on a protected method).
Issue #1 is a result of Settings.Default.MyDirectoryPath being code generated by Visual Studio without any contracts on the property. This issue is not limited to null strings. Many API's now have contracts that require say a TimeSpan to be non-negative but using a setting directly in the API will generate a Code Contracts warning.
A way to solve this issue is to wrap the setting in a method that has a contract. E.g.:
String GetMyDirectoryPath() {
Contract.Ensures(Contract.Result<String>() != null);
var myDirectoryPath = Settings.Default.MyDirectoryPath;
Contract.Assume(myDirectoryPath != null);
return myDirectoryPath;
}
Notice how the Contract.Assume really performs validation of your setting (which can't be verified by Code Contracts because it is controlled by an external configuration file). Had it been a TimeSpan that is expected to be non-negative you can either use Contract.Assume to do the validation resulting in a ContractException or some other method using your own exception instead.
Adding this extra layer is somewhat tedious but because the setting is defined outside the application it needs to be run-time validated at some point just as you have to validate interactive user input.
Issue #2 is probably because DirectoryInfo doesn't have any contracts defined. The easist way is to use Contract.Assume. This will make a statement about what you believe is the expected behavior of DirectoryInfo but a run-time check will still be in place to ensure that your belief is correct (provided that you keep the checks in your code).
var path = MyDirectory.FullName;
Contract.Assume(!string.IsNullOrEmpty(path));
var catalog = new DirectoryCatalog(path);
After having used Code Contracts in a current project for a while now I have found that it does force you to rewrite your code at times to correct for issues. You really have two options here.
You can add the setting to your project settings to output what the correct attributes to apply are to ignore certain warnings. This is done by adding the "-outputwarnmasks" flag to the "Extra Static Checker Options" under the Advanced section in the Code Contracts tab of the Project file settings. This will add information to the Build Output window giving you the correct attributes to add to ignore the individual cases. (very useful when dealing with Entity Framework).
You can rewrite your code to add the proper Requires and Ensures to your code so that the warnings don't appear.
If you want to rewrite the code:
To solve Issue #1 you would have to wrap the Settings class and expose a new MyDirectoryPath as a property that isn't code generated so that you can add a check in it and return an empty string and add the Contract.Ensures(Contract.Result<string>() != null) at the top of the Getter for the property.
To solve Issue #2 you would have to wrap you access to the class field inside a private static property that adds the proper Ensures and Requires.
I have usually gone with rewriting the code wherever possible except with Entity Framework/LINQ where you need to add the attributes, especially with complex queries.
** Disclaimer ** These are just the ways I have found to solve the issues as there isn't a great deal of information on other ways of working around these types of items.
Well, for Issue#2, I think you might want to use && not ||. But beyond that, perhaps for Issue#1 you can put those checks in the static constructor? Another option for Issue#2 is to have the method to take the directory as a parameter:
private static readonly DirectoryInfo MyDirectory;
static MyClass()
{
Contract.Requires(Settings.Default.MyDirectoryPath != null);
MyDirectory = new DirectoryInfo(Settings.Default.MyDirectoryPath);
}
protected void SomeMethod()
{
SomeOtherMethod(MyDirectory);
}
protected virtual void SomeOtherMethod(DirectoryInfo directory)
{
Contract.Requires(directory.Exists && !String.IsNullOrEmpty(directory.FullName));
var catalog = new DirectoryCatalog(directory.FullName);
}
I don't have much experience working with the Contract API, so I might be off my rocker with all this. :)
Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName));
Don't do this! MyDirectory.Exists can change at any time and the caller cannot guarantee it. Just throw an exception if the directory doesn't exist - this is what exceptions are for.

capture changes to properties of an object

I have multiple business objects in my application (C#, Winforms, WinXP). When the user executes some action on the UI, each of these objects are modified and updated by different parts of the application. After each modification, I need to first check what has changed and then log these changes made to the object. The purpose of logging this is to create a comprehensive tracking of activity going on in the application.
Many among these objects contain contain lists of other objects and this nesting can be several levels deep. The 2 main requirements for any solution would be
capture changes as accurately as possible
keep performance cost to minimum.
eg of a business object:
public class MainClass1
{
public MainClass1()
{
detailCollection1 = new ClassDetailCollection1();
detailCollection2 = new ClassDetailCollection2();
}
private Int64 id;
public Int64 ID
{
get { return id; }
set { id = value; }
}
private DateTime timeStamp;
public DateTime TimeStamp
{
get { return timeStamp; }
set { timeStamp = value; }
}
private string category = string.Empty;
public string Category
{
get { return category; }
set { category = value; }
}
private string action = string.Empty;
public string Action
{
get { return action; }
set { action = value; }
}
private ClassDetailCollection1 detailCollection1;
public ClassDetailCollection1 DetailCollection1
{
get { return detailCollection1; }
}
private ClassDetailCollection2 detailCollection2;
public ClassDetailCollection2 DetailCollection2
{
get { return detailCollection2; }
}
//more collections here
}
public class ClassDetailCollection1
{
private List<DetailType1> detailType1Collection;
public List<DetailType1> DetailType1Collection
{
get { return detailType1Collection; }
}
private List<DetailType2> detailType2Collection;
public List<DetailType2> DetailType2Collection
{
get { return detailType2Collection; }
}
}
public class ClassDetailCollection2
{
private List<DetailType3> detailType3Collection;
public List<DetailType3> DetailType3Collection
{
get { return detailType3Collection; }
}
private List<DetailType4> detailType4Collection;
public List<DetailType4> DetailType4Collection
{
get { return detailType4Collection; }
}
}
//more other Types like MainClass1 above...
I can assume that I will have access to the old values and new values of the object.
In that case I can think of 2 ways to try to do this without being told what has explicitly changed.
use reflection and iterate thru all properties of the object and compare
those with the corresponding
properties of the older object. Log
any properties that have changed. This
approach seems to be more flexible, in
that I would not have to worry if any
new properties are added to any of the
objects. But it also seems performance
heavy.
Log changes in the setter of all the properties for all the objects.
Other than the fact that this will
need me to change a lot of code, it
seems more brute force. This will be
maintenance heavy and inflexible if
some one updates any of the Object
Types. But this way it may also be
preformance light since I will not
need to check what changed and log
exactly what properties are changed.
Suggestions for any better approaches and/or improvements to above approaches are welcome
I developed a system like this a few years ago. The idea was to track changes to an object and store those changes in a database, like version control for objects.
The best approach is called Aspect-Oriented Programming, or AOP. You inject "advice" into the setters and getters (actually all method execution, getters and setters are just special methods) allowing you to "intercept" actions taken on the objects. Look into Spring.NET or PostSharp for .NET AOP solutions.
I may not be able to give you a good answer, but I will tell you that in the overwhelming majority of cases, option 1 is NOT a good answer. We're dealing with a very similar reflective "graph-walker" in our project; seemed like a good idea at the time, but it is a nightmare, for the following reasons:
You know the object changed, but without a high level of knowledge in the reflective "change handling" class about the workings of objects above it, you may not know why. If that information is important to you, you have to give it to the change handler, most l;ikely through a field or property on the domain object, requiring changes to your domain and imparting knowledge to the domain about the business logic.
Changes can affect multiple objects, but logs for changes at every level may not be desired; for instance, the client may not want to see a change to a Borrower's outstanding loan count in the log when a new Loan is approved, but they do want to see changes due to consolidations. Managing rules about logging in these cases requires change handling classes to know about more of the structure than just one object, which can very quickly make a change-handling object VERY big, and VERY brittle.
The requirements of your graph walker are probably more than you know; if your object graph includes backreferences or cross-references, the walker must know where it's been, and the simplest comprehensive way to do that is to keep a list of objects it's processed, and check the current object against those it's handled before processing it (making anti-backtracking an N^2 operation). It must also not consider changes to objects in the graph that will not be persisted when you persist the top level (references that are not "cascaded"). NHibernate gives you the ability to plug into its own graph-walker and abide by the cascade rukles in your mappings, which helps, but if you're using a roll-your-own DAL, or you DO want to log changes to objects that NHibernate won't cascade to, you're going to have to set this all up yourself.
A piece of logic in a handler may make a change that requires an update to a "parent" object (updating a calculated field, perhaps). Now, you have to go back and re-evaluate the changed object if the change is of interest to another piece of the change handling logic.
If you have logic that requires creation and persistence of a new object, you must do one of two things; attach the new object to the graph somewhere (where it may or may not be picked up by the walker), or persist the new object in its own transaction (if you're using an ORM, the object CANNOT reference an object from the other graph with a "cascade" setting that will cause it to be saved first).
Finally, being highly reflective in both walking the graph and finding the "handlers" for a particular object, passing a complex tree into such a framework is a guaranteed speed bump in your application.
I think you'll save yourself a lot of headaches if you skip the "change handler" reflective pattern, and include the creation of audit logs or any pre-persistence logic in the "unit of work" you're performing up at the business layer, through a set of "audit loggers". This allows the logic making the changes to employ an algorithm selection pattern such as Command or Strategy to tell your audit framework exactly what kind of change is happening, so it can pick the logger that will produce the required logging messages.
See here how adempiere did the changelog: http://wiki.adempiere.net/Change_Log

What is a good design when trying to build objects from a list of key value pairs?

So if I have a method of parsing a text file and returning a list of a list of key value pairs, and want to create objects from the kvps returned (each list of kvps represents a different object), what would be the best method?
The first method that pops into mind is pretty simple, just keep a list of keywords:
private const string NAME = "name";
private const string PREFIX = "prefix";
and check against the keys I get for the constants I want, defined above. This is a fairly core piece of the project I'm working on though, so I want to do it well; does anyone have any more robust suggestions (not saying there's anything inherently un-robust about the above method - I'm just asking around)?
Edit:
More details have been asked for. I'm working on a little game in my spare time, and I am building up the game world with configuration files. There are four - one defines all creatures, another defines all areas (and their locations in a map), another all objects, and a final one defines various configuration options and things that don't fit else where. With the first three configuration files, I will be creating objects based on the content of the files - it will be quite text-heavy, so there will be a lot of strings, things like names, plurals, prefixes - that sort of thing. The configuration values are all like so:
-
key: value
key: value
-
key: value
key: value
-
Where the '-' line denotes a new section/object.
Take a deep look at the XmlSerializer. Even if you are constrained to not use XML on-disk, you might want to copy some of its features. This could then look like this:
public class DataObject {
[Column("name")]
public string Name { get; set; }
[Column("prefix")]
public string Prefix { get; set; }
}
Be careful though to include some kind of format version in your files, or you will be in hell's kitchen come the next format change.
Making a lot of unwarranted assumptions, I think that the best approach would be to create a Factory that will receive the list of key value pairs and return the proper object or throw an exception if it's invalid (or create a dummy object, or whatever is better in the particular case).
private class Factory {
public static IConfigurationObject Factory(List<string> keyValuePair) {
switch (keyValuePair[0]) {
case "x":
return new x(keyValuePair[1]);
break;
/* etc. */
default:
throw new ArgumentException("Wrong parameter in the file");
}
}
}
The strongest assumption here is that all your objects can be treated partly like the same (ie, they implement the same interface (IConfigurationObject in the example) or belong to the same inheritance tree).
If they don't, then it depends on your program flow and what are you doing with them. But nonetheless, they should :)
EDIT: Given your explanation, you could have one Factory per file type, the switch in it would be the authoritative source on the allowed types per file type and they probably share something in common. Reflection is possible, but it's riskier because it's less obvious and self documenting than this one.
What do you need object for? The way you describe it, you'll use them as some kind (of key-wise) restricted map anyway. If you do not need some kind of inheritance, I'd simply wrap a map-like structure into a object like this:
[java-inspired pseudo-code:]
class RestrictedKVDataStore {
const ALLOWED_KEYS = new Collection('name', 'prefix');
Map data = new Map();
void put(String key, Object value) {
if (ALLOWED_KEYS.contains(key))
data.put(key, value)
}
Object get(String key) {
return data.get(key);
}
}
You could create an interface that matched the column names, and then use the Reflection.Emit API to create a type at runtime that gave access to the data in the fields.
EDIT:
Scratch that, this still applies, but I think what your doing is reading a configuration file and parsing it into this:
List<List<KeyValuePair<String,String>>> itemConfig =
new List<List<KeyValuePair<String,String>>>();
In this case, we can still use a reflection factory to instantiate the objects, I'd just pass in the nested inner list to it, instead of passing each individual key/value pair.
OLD POST:
Here is a clever little way to do this using reflection:
The basic idea:
Use a common base class for each Object class.
Put all of these classes in their own assembly.
Put this factory in that assembly too.
Pass in the KeyValuePair that you read from your config, and in return it finds the class that matches KV.Key and instantiates it with KV.Value
public class KeyValueToObjectFactory
{
private Dictionary _kvTypes = new Dictionary();
public KeyValueToObjectFactory()
{
// Preload the Types into a dictionary so we can look them up later
// Obviously, you want to reuse the factory to minimize overhead, so don't
// do something stupid like instantiate a new factory in a loop.
foreach (Type type in typeof(KeyValueToObjectFactory).Assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(KVObjectBase)))
{
_kvTypes[type.Name.ToLower()] = type;
}
}
}
public KVObjectBase CreateObjectFromKV(KeyValuePair kv)
{
if (kv != null)
{
string kvName = kv.Key;
// If the Type information is in our Dictionary, instantiate a new instance of that class.
Type kvType;
if (_kvTypes.TryGetValue(kvName, out kvType))
{
return (KVObjectBase)Activator.CreateInstance(kvType, kv.Value);
}
else
{
throw new ArgumentException("Unrecognized KV Pair");
}
}
else
{
return null;
}
}
}
#David:
I already have the parser (and most of these will be hand written, so I decided against XML). But that looks like I really nice way of doing it; I'll have to check it out. Excellent point about versioning too.
#Argelbargel:
That looks good too. :')
...This is a fairly core piece of the
project I'm working on though...
Is it really?
It's tempting to just abstract it and provide a basic implementation with the intention of refactoring later on.
Then you can get on with what matters: the game.
Just a thought
<bb />
Is it really?
Yes; I have thought this out. Far be it from me to do more work than neccessary. :')

Categories