version 2 in C#
Created by Will Crowther
SeedPacket has been created from the beginning for extensibility. After all, the logic for data generation is contained in Rules that can be easily removed, replaced, or expanded. Individual Rules have access to a plethora of functionality that is passed in via dependency injection. The Generators are passed in as interfaces that can be easily switched out with new implementations, as can the DataSources and all the source data that popluates the DataSources, can be passed in as an XML / JSON file or string.
We are going to focus on two extensibility points, Custom Extension Methods and Custom Generators
Custom Extension Methods
This example shows a simple yet extremely powerful way to customize data generation for a whole project. The extension method overloads in the SeedPacket.Extensions for the main .Seed() methods have purposely been separated from the actual implementations in the SeedCore class in the root SeedPacket namespace. This means you can easily create your own custom implementation of .Seed() that just works everywhere in you project with your own Rules, defaults and data!
The actual code on this page is trivial as it just uses the customizations from the example Extensions/CustomSeedExtensions.cs in this project. This a good starting point for your own custom extensions with default set to your own liking. It simplifies and removes some of the overloads from the SeedPacket.Extensions version, and set your defaults including that that we are getting our source data from our own XML file. Once you have your ideal solution, you will find it generic enough that you will be able to take it to other projects to use for prototyping.
One thing to note is that the namespace Examples.Extensions is imported into the page, but the SeedPacket.Extensions namespace is NOT. This allows our custom version(s) of .Seed() to work without namespace collisions. Another is that we are using a CustomGenerator that inherits from MultiGenerator. We will look at this a little later on the page.
|1||Take Your Time||Mondo Bondo||The Bobs||9/16/2019|
|2||Life Leasons||The Asking||Sea Lion||5/25/2019|
|3||Seredipity2||The Black Album||Dylan Dylan||8/28/2019|
|4||The Man and the Stars||Gorilla Joint||Fiddly Bits||9/11/2021|
|5||Seredipity2||The Stream||Stalingrad Cowboys||10/23/2021|
|6||Take Your Time||Tin Can Man||Beat The Wind||10/13/2021|
|7||Groovy Tunes||Gangland Frame||Stalingrad Cowboys||3/24/2022|
|8||Life Leasons||Pop of the Tops||Beltway||11/14/2021|
|9||Country Shack||Smoke In Your Eyes||Christian Frizzle||12/25/2021|
|10||The Will and the Way||Know Your Friends||MC Ash||8/27/2019|
SeedOne Extension Method
An additional method included in Examples.Extensions is SeedOne() which is implementation for just getting back a fully-populated single instance of the type. It is an extension on any class that implements the new() constructor (with no creation parameters). While perhaps not the most efficient code, it shows how you can create alternative extensions that utilize SeedPacket code generation.
Another extensibility point demonstrated in the CustomSeedExension.cs class is the custom IGenerator. The CustomGenerator inherits all functionality from the MultiGenerator and adds few new customizations. In this case, it adds a RulesSet.Advanced option as the default and adds some additional rules, including a Rule that fills the CEO property. Of course these could be more extensive, including a completely new default Rules implementation, etc.
The GetRules() method of the MultiGenerator is declared as virtual so that it can be overriden by a derived class. This method is called by the constructor to load its Rules collection based on the RulesSet enum that it is passed. So be overriding it, you can redefine which Rules are loaded for each enum. In fact, 3 values in the enum, Advanced, UnitTest, and Custom do not have an implementation are there purely for customization in derived classes.
Customizing multiple RuleSet implementations, gives you a centalized generator that can be used for unit testing by default and another that is for prototyping, etc.