Have you ever wanted to address some custom serialization case but you couldn’t do it with default predicates? That post might help you.
Introduction
By default Unicorn comes with predicate that allows us to use two types of exlusions:
- PathBasedPresetTreeExclusion
- ChildrenOfPathBasedPresetTreeExclusion
This post describes how to extend default predicate and write your own custom exclusions.
Background
IPresetTreeExclusion
assumes that we want to make a decision based on item’s path only. That limits us from doing something more sophisticated.
1
2
3
4
5
public interface IPresetTreeExclusion
{
PredicateResult Evaluate(string itemPath);
string Description { get; }
}
Just before we pass the path to the Evaluate
method we have access to the IItemData
object
See what else apart from Path
you can find in IItemData
type to build custom exclusion logic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Rainbow.Model
{
public interface IItemData : IItemMetadata
{
string DatabaseName { get; set; }
string Name { get; }
Guid BranchId { get; }
IEnumerable<IItemFieldValue> SharedFields { get; }
IEnumerable<IItemLanguage> UnversionedFields { get; }
IEnumerable<IItemVersion> Versions { get; }
IEnumerable<IItemData> GetChildren();
}
public interface IItemMetadata
{
Guid Id { get; }
Guid ParentId { get; }
Guid TemplateId { get; }
string Path { get; }
string SerializedItemId { get; }
}
}
The main goal is to pass whole IItemData
instead and use all properties/methods inside evaluator.
Let’s do this!
Custom Predicate
To levrage all serialization data we have to overwrite the default SerializationPresetPredicate
.
I won’t go through this process. You can see the whole code in my Sitecore.Playground repository,
CustomSerializationPresetPredicate commit.
I will just highlight few things:
IPresetItemExclusion.cs
- replacement forIPresetTreeExclusion
. It will provide differentEvaluate
method signatureCustomSerializationPresetPredicate.cs
- replacement forSerializationPresetPredicate
. It will be responsible for parsing additional config nodes and invoking advanced exlusionsCustomPresetTreeRoot
- replacement forPresetTreeRoot
. It will extend existing class by addingAdvancedExclusions
collection to the type
1
public IList<IPresetItemExclusion> AdvancedExclusions { get; set; }
That’s it. Now you can write your custom exclusions. Read next section to see how I used it to exclude items by templateId
Following solution does not overwrite default Unicorn functionality, it just enhances existing features.
Custom Exclusions
As an example, I will show you how I implemented exclusion by templateId
The code is pretty easy. Instead of implementing IPresetTreeExclusion
we implement our custom interface: IPresetItemExclusion
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TemplateBasedPresetExclusion : IPresetItemExclusion
{
private readonly string _excludeChildrenOfTemplate;
public TemplateBasedPresetExclusion(string getExpectedAttribute, CustomPresetTreeRoot root)
{
_excludeChildrenOfTemplate = getExpectedAttribute;
}
public string Description => "Exclueds items based on ItemData' template id";
public PredicateResult Evaluate(IItemData itemData)
{
if (itemData.TemplateId.Equals(new Guid(_excludeChildrenOfTemplate)))
{
return new PredicateResult(false);
}
return new PredicateResult(true);
}
}
In the Evaluate
I check whether current TemplateId
is equal to excluded template id from the configuration.
Usage
To use advanced exclusion you just have to do two things:
- change the
type
attribute value ofpredicate
node - add
excludeAdvanced
node into yourinclude
node (this is how I passed thetempalteid
into the code, you can use your own approach)
1
2
3
4
5
<predicate type="Sitecore.Playground.Serialization.Predicates.CustomSerializationPresetPredicate, Sitecore.Playground.Serialization" singleInstance="true">
<include name="Tasks" database="master" path="/sitecore/media library/Default Website">
<excludeAdvanced templateid="{5DD87B05-6652-47D2-92D4-1718D77D8FCD}" />
</include>
</predicate>
Summary
The main goal of this post is to show you how you can extend the default Unicorn predicate. As you can see there are few different properties/methods that you can use to build your own exclusions which should cover your crazy ideas.
Hope you like it ;)