How to effectively test SiteCore LinkField - c#

I have been using moles to write unit tests on the hard to reach parts of my code – particularly where I use the types found in the sitecore class libraries (which are hard to use mocking frameworks with). I have come across a surprisingly tricky problem where I’m trying to mole a LinkField type and test the following kind of code snippet.
LinkField linkField = item.Fields["External Url"];
if (linkField.IsInternal && linkField.TargetItem != null)
{
// want to test this path
item.Fields is a field collection whose indexer returns a type of SiteCore.Data.Field, but LinkField is set up such that uses an implicit operator which hides the conversion which means you are able to work with an instance of LinkField in your code.
My difficulty is that I cannot create a mole of type MLinkField, and assign this to the FieldCollection in the Item as it is strongly typed to Field. Moreover, it seems that whilst I am able to create a type of MField, when the implicit conversion happens, it will work and return an object but none of the fields are set to have any values. This means, I can’t test the code path above which relies on the state of the linkField being set a certain way.
The only way I can think of setting these values is indirectly – i.e. finding what values need to be set by analysing the implicit conversion and setting these in MField. The implicit operator calls the LinkField constructor as follows:
public LinkField(Field innerField) : base(innerField, "link")
which means I need to be conscious of how it instantiates the base type (XmlField), and in turn that class’s base type (CustomField).
Then, to look at what underlying values TargetItem is looking for. The end result is the need to mole out:
InnerField.Database.Items[internalPath];
Or
InnerField.Database.Items[targetID];
Where InnerField is effectively my MField.
Does anyone have a better idea? This sounds horribly convoluted but I think that’s the nature of the beast with these assemblies.

It can be done but you'll need to jump through a few hoops to make it work.
First of all, a bit of background:
LinkField does not inherit from the Field class like some other field types do.
LinkField inherits from XmlField which in turn inherits from CustomField.
CustomField (and it's subtypes) are instantiated by passing a field instance into the constructor.
Linkfields store their values in this field instance.
Linkfields cannot be added to a FieldCollection as they do not inherit from Field.
Rather than add the LinkField we need to add the LinkField's InnerField property.
When a Field is pulled from a FieldCollection and assigned to a LinkField an implicit conversion operation is performed.
The implicit conversion operation creates a new LinkField by passing the selected field to the LinkField's constructor. It is this new LinkField that is returned.
Now some code:
const string externalUrl = "External Url";
const string targetItemName = "Target Item";
Field field = new ShimField { IDGet = () => ID.NewID, NameGet = () => externalUrl };
Item targetitem = new ShimItem { IDGet = () => ID.NewID, NameGet = () => targetItemName };
LinkField linkfield = new ShimLinkField(field) { IsInternalGet = () => true, TargetItemGet = () => targetitem };
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
FieldCollection fields = new ShimFieldCollection { ItemGetString = (name) => linkfield.InnerField };
Item item = new ShimItem { NameGet = () => "Test Item", FieldsGet = () => fields };
And now for a bit of explanation:
The key to making the above code work is the line:
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
By Shimming the implicit conversion operator, we can ensure that when the following line is called:
LinkField linkField = item.Fields["External Url"];
A link field is returned and it's properties are shimmed as you want them.

Since LinkField cannot be mocked in a proper way it have to be used in unit tests "as is" meaning that you'll have to test both your code and the link field implementation.
The good news is that the Link field is an XmlField that operates with the xml data stored in the inner field value. In order to configure the link field behavior you just need to set proper xml in the value.
With Sitecore.FakeDb you can easily create content in memory and configure items and fields you need. The following code creates items home and target. The home item has got Url link field which has TargetId pointed to the target item:
ID targetId = ID.NewID;
using (var db = new Db
{
new DbItem("home")
{
// Field 'Url' is an internal link which targets the 'target' item
{ "Url", "<link linktype=\"internal\" id=\"{0}\" />".FormatWith(targetId) }
},
new DbItem("target", targetId)
})
{
Item item = db.GetItem("/sitecore/content/home");
LinkField linkField = item.Fields["Url"];
linkField.IsInternal.Should().BeTrue();
linkField.TargetItem.Should().NotBeNull();
linkField.TargetItem.Paths.FullPath.Should().Be("/sitecore/content/target");
}

Personally speaking, I do try to abstract Sitecore away from business logic that doesn't need to interact with it directly; however I'm mindful that some things will need to deal with it directly and I try not to take it too far. If you spend too much time abstracting Sitecore out of your logic, then in my opinion you can end up making it more difficult to take advantage of some features that make Sitecore useful.
While unit testing purists may disagree with my approach, I will have unit tests that use the Sitecore API to properly instantiate items. Doing so is fairly straight-forward, I wrote a blog post about it a while ago. Then your only problem is dealing with test data, but it's fairly easy to create it with a test set-up and remove it with a test tear-down.

Related

C# adding properties to already created dynamic object list

I am creating a list like following:
var result = data.Select(p => new
{
p.FirstName,
p.LastName,
Relationship = p.RelationshipType,
p.TierType,
Gender = p.GenderType,
p.AnnualSalary
});
However, I need to add more properties into each of the array item of result like following
foreach(var property in ListOfAdditionalProperties)
{
// Add property logic
}
Is this possible?
I tried ExpandoObject but was not able to come up with the final result list that I get with the Lambda mentioned on top.
No, it's not possible.
You cannot add more members to a dynamic type after the type has been created.
Think of it as a class declaration. Once the class is declared and compiled it cannot be modified.
You need to use another approach, just like the ones you mention. But yes, that has it's drawbacks in regards to syntax.

String as a generic parameter of a new operator

I want to pass a property name as an argument:
protected T findControl<T>(string myProperty, string myPropertyValue , UITestControl control = null) where T : UITestControl, new()
{
var uiContainer = control ?? Window;
return uiContainer.SearchFor<T>(new { myProperty = myPropertyValue });
}
public static T SearchFor<T>(
this UITestControl control,
dynamic searchProperties,
dynamic filterProperties = null) where T : UITestControl, new()
I use:
return findControl<HtmlComboBox>("id", "PersonComboBox")
When debuging, I get:
dynamic searchProperties = {myProperty = PersonComboBox}
what, I would like to is:
dynamic searchProperties = {id = PersonComboBox}
Why is that so? Is there a way to fix that?
Agree with Andrew Sun - dynamics is not very popular feature and it's only usage is dealing with COM interop or with special APIs such Newton.Json,MongoConnector (where it's not very popular too - most developers prefer their Dictionary overload).
If you want impress something dynamic in .net - best way use collections and containers that are mostly close to JS object behavior.
Mostly common used classes for this task is - Dictionary<string,object> (almost exactly same thing as JS object) or Dictionary<string,string> (if it's really string only map and no nesting).
If you must provide nesting - you still can use Dictionary<string,object>, but for some scenarios XElement could be better choice.
I not suggest to use Newton.JSON without large reasone because it's addition dependency and is kind of swiss-knife - you will just use 1% of services it provide.
When think that dynamics are good - remember - it's just hack with not efficient implemenation and it cause CSharp dependency for project and overheat with runtime compilation. I and i think many other people not suggest use them instead of very special cases.
I also agree with my previous speakers that using a Dictionary might be an easier solution here, but if you still want to use dynamics here, you could try the following:
protected T findControl<T>(string myProperty, string myPropertyValue, UITestControl control = null) where T : UITestControl, new()
{
var uiContainer = control ?? Window;
// create an expando object here and reference it as dictionary
IDictionary<string, object> searchProperties = new ExpandoObject();
// now add your data to the dictionary
searchProperties.Add(myProperty, myPropertyValue);
// call your method with your newly created expando object,
// in your method, you can now call "searchProperties.id"
// and also your debug view (open the "Dynamic View" item in VS debugger)
// should show a property called "id"
return uiContainer.SearchFor<T>(searchProperties);
}

What is the purpose of nameof?

Version 6.0 got a new feature of nameof, but I can't understand the purpose of it, as it just takes the variable name and changes it to a string on compilation.
I thought it might have some purpose when using <T> but when I try to nameof(T) it just prints me a T instead of the used type.
Any idea on the purpose?
What about cases where you want to reuse the name of a property, for example when throwing exception based on a property name, or handling a PropertyChanged event. There are numerous cases where you would want to have the name of the property.
Take this example:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
In the first case, renaming SomeProperty will cause a compilation error if you don't change both the property definition and the nameof(SomeProperty) expression. In the second case, renaming SomeOtherProperty or altering the "SomeOtherProperty" string will result in silently broken runtime behavior, with no error or warning at build time.
This is a very useful way to keep your code compiling and bug free (sort-of).
(A very nice article from Eric Lippert why infoof didn't make it, while nameof did)
It's really useful for ArgumentException and its derivatives:
public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...
Now if someone refactors the name of the input parameter the exception will be kept up to date too.
It is also useful in some places where previously reflection had to be used to get the names of properties or parameters.
In your example nameof(T) gets the name of the type parameter - this can be useful too:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
Another use of nameof is for enums - usually if you want the string name of an enum you use .ToString():
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
This is actually relatively slow as .Net holds the enum value (i.e. 7) and finds the name at run time.
Instead use nameof:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
Now .Net replaces the enum name with a string at compile time.
Yet another use is for things like INotifyPropertyChanged and logging - in both cases you want the name of the member that you're calling to be passed to another method:
// Property with notify of change
public int Foo
{
get { return this.foo; }
set
{
this.foo = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
}
}
Or...
// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
Log(nameof(DoSomething), "Message....");
}
Another use-case where nameof feature of C# 6.0 becomes handy - Consider a library like Dapper which makes DB retrievals much easier. Albeit this is a great library, you need to hardcode property/field names within query. What this means is that if you decide to rename your property/field, there are high chances that you will forget to update query to use new field names. With string interpolation and nameof features, code becomes much easier to maintain and typesafe.
From the example given in link
without nameof
var dog = connection.Query<Dog>(
"select Age = #Age, Id = #Id",
new {Age = (int?) null, Id = guid});
with nameof
var dog = connection.Query<Dog>(
$"select {nameof(Dog.Age)} = #Age, {nameof(Dog.Id)} = #Id",
new {Age = (int?) null, Id = guid});
Your question already expresses the purpose. You must see this might be useful for logging or throwing exceptions.
For example:
public void DoStuff(object input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
}
This is good. If I change the name of the variable, the code will break instead of returning an exception with an incorrect message.
Of course, the uses are not limited to this simple situation. You can use nameof whenever it would be useful to code the name of a variable or property.
The uses are manifold when you consider various binding and reflection situations. It's an excellent way to bring what were run time errors to compile time.
The most common use case I can think of is when working with the INotifyPropertyChanged interface. (Basically everything related to WPF and bindings uses this interface)
Take a look at this example:
public class Model : INotifyPropertyChanged
{
// From the INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
private string foo;
public String Foo
{
get { return this.foo; }
set
{
this.foo = value;
// Old code:
PropertyChanged(this, new PropertyChangedEventArgs("Foo"));
// New Code:
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));
}
}
}
As you can see in the old way we have to pass a string to indicate which property has changed. With nameof we can use the name of the property directly. This might not seem like a big deal. But image what happens when somebody changes the name of the property Foo. When using a string the binding will stop working, but the compiler will not warn you. When using nameof you get a compiler error that there is no property/argument with the name Foo.
Note that some frameworks use some reflection magic to get the name of the property, but now we have nameof this is no longer neccesary.
Most common usage will be in input validation, such as
//Currently
void Foo(string par) {
if (par == null) throw new ArgumentNullException("par");
}
//C# 6 nameof
void Foo(string par) {
if (par == null) throw new ArgumentNullException(nameof(par));
}
In first case, if you refactor the method changing par parameter's name, you'll probably forget to change that in the ArgumentNullException. With nameof you don't have to worry about that.
See also: nameof (C# and Visual Basic Reference)
The ASP.NET Core MVC project uses nameof in the AccountController.cs and ManageController.cs with the RedirectToAction method to reference an action in the controller.
Example:
return RedirectToAction(nameof(HomeController.Index), "Home");
This translates to:
return RedirectToAction("Index", "Home");
and takes takes the user to the 'Index' action in the 'Home' controller, i.e. /Home/Index.
Let's say you need to print the name of a variable in your code. If you write:
int myVar = 10;
print("myVar" + " value is " + myVar.toString());
and then if someone refactors the code and uses another name for myVar, he/she would have to look for the string value in your code and change it accordingly.
Instead, if you write:
print(nameof(myVar) + " value is " + myVar.toString());
It would help to refactor automatically!
The MSDN article lists MVC routing (the example that really clicked the concept for me) among several others. The (formatted) description paragraph reads:
When reporting errors in code,
hooking up model-view-controller (MVC) links,
firing property changed events, etc.,
you often want to
capture the string name of a method. Using nameof helps keep your code
valid when renaming definitions.
Before you had to use string literals
to refer to definitions, which is brittle when renaming code elements
because tools do not know to check these string literals.
The accepted / top rated answers already give several excellent concrete examples.
As others have already pointed out, the nameof operator does insert the name that the element was given in the sourcecode.
I would like to add that this is a really good idea in terms of refactoring since it makes this string refactoring safe. Previously, I used a static method which utilized reflection for the same purpose, but that has a runtime performance impact. The nameof operator has no runtime performance impact; it does its work at compile time. If you take a look at the MSIL code you will find the string embedded. See the following method and its disassembled code.
static void Main(string[] args)
{
Console.WriteLine(nameof(args));
Console.WriteLine("regular text");
}
// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret
However, that can be a drawback if you plan to obfuscate your software. After obfuscation the embedded string may no longer match the name of the element. Mechanisms that rely on this text will break. Examples for that, including but not limited to are: Reflection, NotifyPropertyChanged ...
Determining the name during runtime costs some performance, but is safe for obfuscation. If obfuscation is neither required nor planned, I would recommend using the nameof operator.
The purpose of the nameof operator is to provide the source name of the artifacts.
Usually the source name is the same name as the metadata name:
public void M(string p)
{
if (p == null)
{
throw new ArgumentNullException(nameof(p));
}
...
}
public int P
{
get
{
return p;
}
set
{
p = value;
NotifyPropertyChanged(nameof(P));
}
}
But this may not always be the case:
using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"
Or:
public static string Extension<T>(this T t)
{
return nameof(T); returns "T"
}
One use I've been giving to it is for naming resources:
[Display(
ResourceType = typeof(Resources),
Name = nameof(Resources.Title_Name),
ShortName = nameof(Resources.Title_ShortName),
Description = nameof(Resources.Title_Description),
Prompt = nameof(Resources.Title_Prompt))]
The fact is that, in this case, I didn't even need the generated properties to access the resources, but now I have a compile time check that the resources exist.
The purpose of nameof is refactoring. For example when you change the name of a class to which you refer to through nameof somewhere else in your code you will get a compilation error which is what you want. If you didn't use nameof and had just a plain string as a reference you'd have to fulltext search for the name of the class in order to change it. That's a pain in the bottom. With nameof you can rest easy, build, and get all the cases for change automatically in your IDE.
Another use case of nameof is to check tab pages, instead of checking the index you can check the Name property of the tabpages as follow:
if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
// Do something
}
Less messy :)
I find that nameof increases the readability of very long and complex SQL statements in my applications. It makes the variables stand out of that sea of strings and eliminates your job of figuring out where the variables are used in your SQL statements.
public bool IsFooAFoo(string foo, string bar)
{
var aVeryLongAndComplexQuery = $#"SELECT yada, yada
-- long query in here
WHERE fooColumn = #{nameof(foo)}
AND barColumn = #{nameof(bar)}
-- long query here";
SqlParameter[] parameters = {
new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
}
}
One of the usage of nameof keyword is for setting Binding in wpf programmatically.
to set Binding you have to set Path with string, and with nameof keyword, it's possible to use Refactor option.
For example, if you have IsEnable dependency property in your UserControl and you want to bind it to IsEnable of some CheckBox in your UserControl, you can use these two codes:
CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
and
CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
It's obvious the first code can't refactor but the secend one...
Previously we were using something like that:
// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
var propName = GetPropNameFromExpr(property);
SetFieldsReadOnly(propName);
}
private void SetFieldReadOnly(string propertyName)
{
...
}
Reason - compile time safety. No one can silently rename property and break code logic. Now we can use nameof().
It has advantage when you use ASP.Net MVC. When you use HTML helper to build some control in view it uses property names in name attribure of html input:
#Html.TextBoxFor(m => m.CanBeRenamed)
It makes something like that:
<input type="text" name="CanBeRenamed" />
So now, if you need to validate your property in Validate method you can do this:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (IsNotValid(CanBeRenamed)) {
yield return new ValidationResult(
$"Property {nameof(CanBeRenamed)} is not valid",
new [] { $"{nameof(CanBeRenamed)}" })
}
}
In case if you rename you property using refactoring tools, your validation will not be broken.

Reflection, contravariance and polymorphism

I have a base class (abstract) with multiple implementations, and some of them contain collection properties of other implementations - like so:
class BigThing : BaseThing
{
/* other properties omitted for brevity */
List<SquareThing> Squares { get; set; }
List<LittleThing> SmallThings { get; set;}
/* etc. */
}
Now sometimes I get a BigThing and I need to map it to another BigThing, along with all of its collections of BaseThings. However, when this happens, I need to be able to tell if a BaseThing in a collection from the source BigThing is a new BaseThing, and thus should be Add()-ed to the destination BigThing's collection, or if it's an existing BaseThing that should be mapped to one of the BaseThings that already exist in the destination collection. Each implementation of BaseThing has a different set of matching criteria on which it should be evaluated for new-ness. I have the following generic extension method to evaluate this:
static void UpdateOrCreateThing<T>(this T candidate, ICollection<T> destinationEntities) where T : BaseThing
{
var thingToUpdate = destinationEntites.FirstOrDefault(candidate.ThingMatchingCriteria);
if (thingToUpdate == null) /* Create new thing and add to destinationEntities */
else /* Map thing */
}
Which works fine. However I think I am getting lost with the method that deals in BigThings. I want to make this method generic because there are a few different kinds of BigThings, and I don't want to have to write methods for each, and if I add collection properties I don't want to have to change my methods. I have written the following generic method that makes use of reflection, but it is not
void MapThing(T sourceThing, T destinationThing) where T : BaseThing
{
//Take care of first-level properties
Mapper.Map(sourceThing, destinationThing);
//Now find all properties which are collections
var collectionPropertyInfo = typeof(T).GetProperties().Where(p => typeof(ICollection).IsAssignableFrom(p.PropertyType));
//Get property values for source and destination
var sourceProperties = collectionPropertyInfo.Select(p => p.GetValue(sourceThing));
var destinationProperties = collectionPropertyInfo.Select(p => p.GetValue(destinationThing));
//Now loop through collection properties and call extension method on each item
for (int i = 0; i < collectionPropertyInfo.Count; i++)
{
//These casts make me suspicious, although they do work and the values are retained
var thisSourcePropertyCollection = sourceProperties[i] as ICollection;
var sourcePropertyCollectionAsThings = thisSourcePropertyCollection.Cast<BaseThing>();
//Repeat for destination properties
var thisDestinationPropertyCollection = destinationProperties[i] as ICollection;
var destinationPropertyCollectionAsThings = thisDestinationPropertyCollection.Cast<BaseThing>();
foreach (BaseThing thing in sourcePropertyCollectionAsThings)
{
thing.UpdateOrCreateThing(destinationPropertyCollectionAsThings);
}
}
}
This compiles and runs, and the extension method runs successfully (matching and mapping as expected), but the collection property values in destinationThing remain unchanged. I suspect I have lost the reference to the original destinationThing properties with all the casting and assigning to other variables and so on. Is my approach here fundamentally flawed? Am I missing a more obvious solution? Or is there some simple bug in my code that's leading to the incorrect behavior?
Without thinking too much, I'd say you have fallen to a inheritance abuse trap, and now trying to save yourself, you might want to consider how can you solve your problem while ditching the existing design which leads you to do such things at the first place. I know, this is painful, but it's an investment in future :-)
That said,
var destinationPropertyCollectionAsThings =
thisDestinationPropertyCollection.Cast<BaseThing>();
foreach (BaseThing thing in sourcePropertyCollectionAsThings)
{
thing.UpdateOrCreateThing(destinationPropertyCollectionAsThings);
}
You are losing your ICollection when you use Linq Cast operator that creates the new IEnumerable<BaseThing>. You can't use contravariance either, because ICollectiondoes not support it. If it would, you'd get away with as ICollection<BaseThing> which would be nice.
Instead, you have to build the generic method call dynamically, and invoke it. The simplest way is probably using dynamic keyword, and let the runtime figure out, as such:
thing.UpdateOrCreateThing((dynamic)thisDestinationPropertyCollection);

Deep Reflection in .NET

I need to create the ability to drill through an objects properties like two or three deep. For instance, class A has a property reference to class B, which I need to access class C. What is the best way to do this: straight reflection, or maybe using the TypeDescriptor, or something else?
Thanks.
It's not too hard to write. I put a few classes together to deal with this so I could serialize properties of a WinForm. Take a look at this class and the related classes.
http://csharptest.net/browse/src/Library/Reflection/PropertySerializer.cs
If you know the path in a static context (ie the path is always the same) and the properties are accessible (internal or public) you can use dynamic
[Test]
public void Foo()
{
var a = new A
{
B = new B
{
C = new C
{
Name = "hello"
}
}
};
DoReflection(a);
}
private void DoReflection(dynamic value)
{
string message = value.B.C.Name;
Debug.WriteLine(message);
}
I you wanna write you own serialization code for whatever reason, you'll be using reflection.
What you do is that you write a recursive method of serlizating a type. You then apply this as you see fit to get the result.
var type = myObjectOfSomeType.GetType();
// now depending on what you want to store
// I'll save all public properties
var properties = type.GetProperties(); // get all public properties
foreach(var p in properties)
{
var value = p.GetValue(myObjectOfSomeType, null);
Writevalue(p.Name, value);
}
The implementation of WriteValue have to recognize the built in types and treat them accordingly, that's typical things like string, char, integer, double, DateTime etc.
If it encounters a sequence or collection you need to write out many values.
If it encounters a non trivial type you'll apply this recursive pattern again.
The end result is a recursive algorithm that traverses your object model and writes out values as it encounters types that I know how to serialize.
However, I do recommend looking into WCF, not for building services, but for serialization. It shipped as part of the .NET 3.0 framework with a new assembly System.Runtime.Serilization and in general is very capable when dealing with serialization and data annotations.

Categories

Resources