Multiple inheritance with interfaces
The engine records every interface a type implements as a parent node type. So you can define small, focused facet interfaces:
// A thing that sits somewhere on the map.
public interface ILocatable {
[GeoCoordinateProperty(Indexed = true)]
GeoCoordinate Location { get; set; }
[StringProperty(Indexed = true, MaxLength = 2)]
string CountryCode { get; set; }
}
// A thing with an identity, a name and a slug.
public interface INamedNode {
Guid Id { get; set; }
NodeMeta Meta { get; }
[StringProperty(Indexed = true, IndexedByWords = true, PrefixSearch = true, DisplayName = true)]
string Title { get; set; }
[AddressProperty]
string Slug { get; } // the node's address, set with db.UpdateAddress
}
// A thing with a searchable rich-text body.
public interface IDescribed {
[HtmlProperty(IndexedByWords = true, IndexedBySemantic = true)]
string Description { get; set; }
}
// A thing that can be tagged.
public interface ITagged {
[StringArrayProperty(Indexed = true)]
string[] Tags { get; set; }
}Then compose them per type:
public interface IVenue : INamedNode, IDescribed, ILocatable, ITagged { /* venue-only */ }
public interface IEvent : INamedNode, IDescribed, ITagged { /* event-only */ }
public interface IAttendee : INamedNode, ILocatable { /* attendee-only */ }Each facet's properties are declared once, with their indexing and validation, and every type that
implements the facet gets them. A new type that belongs on the map needs one more interface and
nothing else. With classes, Venue could inherit only one base class, so you would copy properties
between types and keep their attributes in sync by hand.