├── .gitignore ├── FluentInterfaceExample.Types ├── Character.cs ├── ExpressionBuilder │ ├── CharacterBuilder.cs │ └── Interface │ │ ├── ICharacterBuilderAge.cs │ │ ├── ICharacterBuilderClassType.cs │ │ └── ICharacterBuilderStats.cs ├── FluentInterfaceExample.Types.csproj └── Properties │ └── AssemblyInfo.cs ├── FluentInterfaceExample.sln ├── FluentInterfaceExample ├── CommonHelper.cs ├── FluentInterfaceExample.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs └── README.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.cache 2 | *.dll 3 | *.pdb 4 | *.txt 5 | !README.txt 6 | *.suo 7 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/Character.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FluentInterfaceExample.Types 7 | { 8 | /// 9 | /// Simple RPG Character class. 10 | /// 11 | public sealed class Character 12 | { 13 | /// 14 | /// Enum for Character class type. 15 | /// 16 | public enum ClassType 17 | { 18 | Fighter, 19 | Mage, 20 | Cleric, 21 | Rouge 22 | }; 23 | 24 | public string Name; 25 | public ClassType Class; 26 | public int Age; 27 | public int Strength; 28 | public int Agility; 29 | public int Intelligence; 30 | public int Gold; 31 | public int HP; 32 | public int MaxHP; 33 | public bool IsAlive 34 | { 35 | get 36 | { 37 | return HP > 0; 38 | } 39 | } 40 | 41 | public Character() 42 | { 43 | } 44 | 45 | public Character(string name) 46 | { 47 | Name = name; 48 | } 49 | 50 | public Character(string name, ClassType classType, int age, int hp, int strength, int agility, int intelligence, int gold) 51 | { 52 | Name = name; 53 | Class = classType; 54 | Age = age; 55 | MaxHP = hp; 56 | HP = hp; 57 | Strength = strength; 58 | Agility = agility; 59 | Intelligence = intelligence; 60 | Gold = gold; 61 | } 62 | 63 | public override string ToString() 64 | { 65 | string result = "Name: " + Name + "\nClass: " + Class.ToString() + "\nHP: " + HP + "/" + MaxHP + "\nAge: " + Age + "\nStr " + Strength + " / Agi " + Agility + " / Int " + Intelligence + "\nGold: " + Gold; 66 | return result; 67 | } 68 | 69 | public string QuickStats() 70 | { 71 | string result = Name + " (" + HP + "/" + MaxHP + ")"; 72 | return result; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/ExpressionBuilder/CharacterBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using FluentInterfaceExample.Types; 6 | using FluentInterfaceExample.Types.ExpressionBuilder.Interface; 7 | 8 | namespace FluentInterfaceExample.Types.ExpressionBuilder 9 | { 10 | /// 11 | /// Expression builder class for Character, using method chaining with progressive interfaces. 12 | /// 13 | public class CharacterBuilder : ICharacterBuilderClassType, ICharacterBuilderAge, ICharacterBuilderStats 14 | { 15 | private Character _character; 16 | 17 | public ICharacterBuilderClassType Create(string name) 18 | { 19 | _character = new Character(name); 20 | return this; 21 | } 22 | 23 | public ICharacterBuilderAge As(Character.ClassType classType) 24 | { 25 | _character.Class = classType; 26 | return this; 27 | } 28 | 29 | public ICharacterBuilderStats WithAge(int age) 30 | { 31 | _character.Age = age; 32 | return this; 33 | } 34 | 35 | public ICharacterBuilderStats Str(int strength) 36 | { 37 | _character.Strength = strength; 38 | return this; 39 | } 40 | 41 | public ICharacterBuilderStats Agi(int agility) 42 | { 43 | _character.Agility = agility; 44 | return this; 45 | } 46 | 47 | public ICharacterBuilderStats Int(int intelligence) 48 | { 49 | _character.Intelligence = intelligence; 50 | return this; 51 | } 52 | 53 | public ICharacterBuilderStats HP(int hp) 54 | { 55 | _character.HP = hp; 56 | _character.MaxHP = hp; 57 | return this; 58 | } 59 | 60 | public ICharacterBuilderStats Gold(int gold) 61 | { 62 | _character.Gold = gold; 63 | return this; 64 | } 65 | 66 | public Character Value() 67 | { 68 | return _character; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/ExpressionBuilder/Interface/ICharacterBuilderAge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FluentInterfaceExample.Types.ExpressionBuilder.Interface 7 | { 8 | public interface ICharacterBuilderAge 9 | { 10 | ICharacterBuilderStats WithAge(int age); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/ExpressionBuilder/Interface/ICharacterBuilderClassType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FluentInterfaceExample.Types.ExpressionBuilder.Interface 7 | { 8 | public interface ICharacterBuilderClassType 9 | { 10 | ICharacterBuilderAge As(Character.ClassType classType); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/ExpressionBuilder/Interface/ICharacterBuilderStats.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FluentInterfaceExample.Types.ExpressionBuilder.Interface 7 | { 8 | public interface ICharacterBuilderStats 9 | { 10 | ICharacterBuilderStats HP(int hp); 11 | ICharacterBuilderStats Str(int strength); 12 | ICharacterBuilderStats Agi(int agility); 13 | ICharacterBuilderStats Int(int intelligence); 14 | ICharacterBuilderStats Gold(int gold); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/FluentInterfaceExample.Types.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D} 9 | Library 10 | Properties 11 | FluentInterfaceExample.Types 12 | FluentInterfaceExample.Types 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /FluentInterfaceExample.Types/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluentInterfaceExample.Types")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluentInterfaceExample.Types")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8f94eba8-56e3-49a9-b836-98f196e63fc6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FluentInterfaceExample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentInterfaceExample", "FluentInterfaceExample\FluentInterfaceExample.csproj", "{91F30800-B6C3-4242-884D-66F82B782B9C}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentInterfaceExample.Types", "FluentInterfaceExample.Types\FluentInterfaceExample.Types.csproj", "{2C75419B-1857-4B08-A7B2-7AAE56E3B04D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|Mixed Platforms = Debug|Mixed Platforms 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|Mixed Platforms = Release|Mixed Platforms 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Debug|Any CPU.ActiveCfg = Debug|x86 19 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 20 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Debug|Mixed Platforms.Build.0 = Debug|x86 21 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Debug|x86.ActiveCfg = Debug|x86 22 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Debug|x86.Build.0 = Debug|x86 23 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Release|Any CPU.ActiveCfg = Release|x86 24 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Release|Mixed Platforms.ActiveCfg = Release|x86 25 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Release|Mixed Platforms.Build.0 = Release|x86 26 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Release|x86.ActiveCfg = Release|x86 27 | {91F30800-B6C3-4242-884D-66F82B782B9C}.Release|x86.Build.0 = Release|x86 28 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 31 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 32 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Debug|x86.ActiveCfg = Debug|Any CPU 33 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 36 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Release|Mixed Platforms.Build.0 = Release|Any CPU 37 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D}.Release|x86.ActiveCfg = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /FluentInterfaceExample/CommonHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using FluentInterfaceExample.Types; 7 | 8 | namespace FluentInterfaceExample 9 | { 10 | /// 11 | /// Helper class to store our static strings and helper methods. 12 | /// 13 | public static class CommonHelper 14 | { 15 | #region String Helpers 16 | 17 | /// 18 | /// Words used for enemy first names. 19 | /// 20 | private static readonly string[] _firstNames = 21 | { 22 | "Destro", 23 | "Victo", 24 | "Mozri", 25 | "Fang", 26 | "Ovi", 27 | "Hell", 28 | "Syth", 29 | "End" 30 | }; 31 | 32 | /// 33 | /// Words used for enemy last names. 34 | /// 35 | private static readonly string[] _lastNames = 36 | { 37 | "math", 38 | "rin", 39 | "sith", 40 | "icous", 41 | "ravage", 42 | "wrath", 43 | "ryn", 44 | "less" 45 | }; 46 | 47 | /// 48 | /// Verbs used for attacking. 49 | /// 50 | private static readonly string[] _attackVerbs = 51 | { 52 | "slashes", 53 | "stabs", 54 | "smashes", 55 | "impales", 56 | "poisons", 57 | "shoots", 58 | "incinerates", 59 | "destroys" 60 | }; 61 | 62 | /// 63 | /// Generates a random name from the static string lists. 64 | /// 65 | /// Random name 66 | public static string GenerateRandomName() 67 | { 68 | string result = ""; 69 | 70 | Random ran = new Random((int)DateTime.Now.Ticks); 71 | result = _firstNames[ran.Next(_firstNames.Length)] + _lastNames[ran.Next(_lastNames.Length)]; 72 | 73 | return result; 74 | } 75 | 76 | #endregion 77 | 78 | /// 79 | /// Simple suspense text. 80 | /// 81 | /// Character 82 | /// Character 83 | public static void DisplayStartOfBattle(Character hero, Character enemy) 84 | { 85 | // Size up the battle statistics. 86 | Console.WriteLine("= Starting Battle ="); 87 | Console.WriteLine(hero.ToString()); 88 | Console.WriteLine(); 89 | Console.WriteLine("vs."); 90 | Console.WriteLine(); 91 | Console.WriteLine(enemy.ToString()); 92 | Console.WriteLine(); 93 | 94 | // Add suspense. 95 | Console.Write("An enemy approaches> "); 96 | Console.ReadKey(); 97 | Console.WriteLine(); 98 | Console.WriteLine(); 99 | } 100 | 101 | /// 102 | /// Simple battle system. 103 | /// 104 | /// Character 105 | /// Character 106 | public static void Battle(Character hero, Character enemy) 107 | { 108 | // Battle the enemy. 109 | while (hero.IsAlive && enemy.IsAlive) 110 | { 111 | // Print quick stats. 112 | Console.WriteLine(hero.QuickStats() + " / " + enemy.QuickStats()); 113 | 114 | Thread.Sleep(1000); 115 | 116 | // Hero attacks! 117 | Console.WriteLine(Attack(hero, enemy)); 118 | 119 | Thread.Sleep(1000); 120 | 121 | // Enemy attacks! 122 | Console.WriteLine(Attack(enemy, hero)); 123 | 124 | // Prompt for next round of combat. 125 | if (hero.IsAlive) 126 | { 127 | Console.Write(">"); 128 | Console.ReadKey(); 129 | } 130 | 131 | Console.WriteLine(); 132 | } 133 | 134 | // Analyze battle results. 135 | if (hero.IsAlive) 136 | { 137 | // Hero won! 138 | hero.Gold += enemy.Gold; 139 | 140 | Console.WriteLine("Our hero survies to fight another battle! Won " + enemy.Gold + " gold!"); 141 | 142 | Console.Write(">"); 143 | Console.ReadKey(); 144 | Console.Clear(); 145 | } 146 | else 147 | { 148 | // Enemy won! 149 | Console.WriteLine("Our hero has fallen with " + hero.Gold + " gold! The world is covered in darkness once again."); 150 | } 151 | } 152 | 153 | /// 154 | /// Attacks a Character and returns status message. 155 | /// 156 | /// Character initiating attack 157 | /// Character to attack 158 | /// Status message 159 | private static string Attack(Character attacker, Character defender) 160 | { 161 | string result = ""; 162 | 163 | Random ran = new Random((int)DateTime.Now.Ticks); 164 | 165 | // Calculate damage. 166 | int damage = ran.Next(10); 167 | 168 | // Deduct damage from defender's HP. 169 | defender.HP -= damage; 170 | 171 | // Select an attack verb. 172 | string verb = _attackVerbs[ran.Next(_attackVerbs.Length)]; 173 | 174 | // Create status message. 175 | result = attacker.Name + " " + verb + " " + defender.Name + " for " + damage + " damage!"; 176 | 177 | return result; 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /FluentInterfaceExample/FluentInterfaceExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {91F30800-B6C3-4242-884D-66F82B782B9C} 9 | Exe 10 | Properties 11 | FluentInterfaceExample 12 | FluentInterfaceExample 13 | v4.0 14 | Client 15 | 512 16 | 17 | 18 | x86 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x86 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {2C75419B-1857-4B08-A7B2-7AAE56E3B04D} 53 | FluentInterfaceExample.Types 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /FluentInterfaceExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using FluentInterfaceExample.Types; 6 | using FluentInterfaceExample.Types.ExpressionBuilder; 7 | 8 | namespace FluentInterfaceExample 9 | { 10 | /// 11 | /// 12 | /// This is an example of using an internal domain specific language (DSL) for providing domain-readable code. 13 | /// Uses the Expression Builder pattern with method chaining and progressive interfaces to create a simple RPG battle game. 14 | /// 15 | /// By Kory Becker 16 | /// http://www.primaryobjects.com/articledirectory.aspx 17 | /// 18 | /// 19 | class Program 20 | { 21 | static void Main(string[] args) 22 | { 23 | Random ran = new Random((int)DateTime.Now.Ticks); 24 | CharacterBuilder builder = new CharacterBuilder(); 25 | 26 | // Build our Character with the expression builder. 27 | builder.Create("Valient") 28 | .As(Character.ClassType.Fighter) 29 | .WithAge(22) 30 | .HP(20) 31 | .Str(18) 32 | .Agi(14) 33 | .Int(12); 34 | 35 | // Get our Character. 36 | Character hero = builder.Value(); 37 | 38 | // Put our hero to battle against endless enemies, and see how long he survives! 39 | while (hero.IsAlive) 40 | { 41 | // Build an enemy with the expression builder. 42 | builder.Create(CommonHelper.GenerateRandomName()) 43 | .As((Character.ClassType)ran.Next(4)) 44 | .WithAge(ran.Next(12, 200)) 45 | .HP(ran.Next(5, 12)) 46 | .Str(ran.Next(21)) 47 | .Agi(ran.Next(21)) 48 | .Int(ran.Next(21)) 49 | .Gold(ran.Next(50)); 50 | 51 | // Get our enemy. 52 | Character enemy = builder.Value(); 53 | 54 | // Display start of battle. 55 | CommonHelper.DisplayStartOfBattle(hero, enemy); 56 | 57 | // Battle time! 58 | CommonHelper.Battle(hero, enemy); 59 | } 60 | 61 | Console.ReadKey(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /FluentInterfaceExample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluentInterfaceExample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluentInterfaceExample")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6d70c868-9a25-48f6-9a52-2bbbdb634dad")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/primaryobjects/Fluent-Simple-RPG-Game/35d9c8e4e8a1ceecbf84ec401e281f931f21f148/README.txt --------------------------------------------------------------------------------