├── --wait ├── .gitattributes ├── .gitignore ├── AbstractFactory ├── AbstractFactory.csproj ├── Cars │ ├── AbstractCars │ │ ├── FamilyCar.cs │ │ └── SportsCar.cs │ └── ConcreteCars │ │ ├── AudiFamilyCar.cs │ │ ├── AudiSportsCar.cs │ │ ├── MercedesFamilyCar.cs │ │ └── MercedesSportsCar.cs ├── Client │ └── Driver.cs ├── Factory │ ├── AnstractFactory │ │ └── CarFactory.cs │ ├── ConcreteFactory │ │ ├── AudiFactory.cs │ │ └── MercedesFactory.cs │ └── GenericFactory.cs └── Program.cs ├── Adapter ├── Adapted │ ├── DatabaseHelper.cs │ ├── WebSiteScanner.cs │ └── XmlFileLoader.cs ├── Adapter.csproj ├── Adapter │ ├── Connector.cs │ ├── DatabaseConnector.cs │ ├── HttpStreamConnector.cs │ └── XmlFileConnector.cs ├── Client │ └── TradingDataImporter.cs └── Program.cs ├── Bridge ├── Abstraction │ └── Repository.cs ├── AbstractionRefined │ ├── ClientRepository.cs │ └── ProductRepository.cs ├── Bridge.csproj ├── ImplementorAbstract │ └── DataObject.cs ├── ImplementorConcrete │ ├── ClientDataObject.cs │ └── ProductDataObject.cs └── Program.cs ├── Builder ├── Builder.csproj ├── Builder │ ├── AbstractBuilder │ │ └── IPhoneBuilder.cs │ ├── ConcreteBuilder │ │ ├── AndroidPhoneBuilder.cs │ │ └── WindowsPhoneBuilder.cs │ ├── Director │ │ └── Manufacturer.cs │ ├── Object │ │ └── MobilePhone.cs │ └── Parts │ │ ├── BatteryCapacity.cs │ │ ├── Os.cs │ │ ├── ScreenType.cs │ │ └── Stylus.cs ├── FluentBuilder │ ├── House.cs │ ├── HouseBuilder.cs │ └── IHouseBuilder.cs └── Program.cs ├── CSharpDesignPatterns.sln ├── ChainOfResponsibility ├── Abstrations │ └── Handler.cs ├── ChainOfResponsibility.csproj ├── Implementations │ ├── ConcreteHandler1.cs │ ├── ConcreteHandler2.cs │ └── ConcreteHandler3.cs └── Program.cs ├── Command ├── Client │ └── Program.cs ├── Command.csproj ├── CommandInvoker │ └── Switch.cs ├── Commands │ ├── CloseSwitchCommand.cs │ ├── ICommand.cs │ └── OpenSwitchCommand.cs └── Receiver │ ├── ISwitchable.cs │ └── Light.cs ├── Composite ├── ComponentObject │ ├── CompositeGraphic.cs │ └── IGraphic.cs ├── Composite.csproj ├── LeafObject │ └── Leaf.cs └── Program.cs ├── Decorator ├── Component │ ├── ICoffee.cs │ └── SimpleCoffee.cs ├── Decorator.csproj ├── Decorator │ ├── CoffeeDecorator.cs │ ├── CoffeeWithMilk.cs │ └── CoffeeWithSprinkles.cs └── Program.cs ├── Facade ├── CarFacade │ └── CarFacade.cs ├── CarParts │ ├── CarAccessories.cs │ ├── CarBody.cs │ ├── CarEngine.cs │ └── CarModel.cs ├── Facade.csproj └── Program.cs ├── Flyweight ├── Flyweight.csproj ├── NormalImplementation │ ├── Clients │ │ └── CoffeeMaker.cs │ ├── CoffeeFlavour.cs │ ├── ICoffeeFlavourFactory.cs │ ├── Minimal │ │ └── MinimumMemoryFootprint.cs │ └── ReducedMemoryFootprintFlavorFactory.cs ├── Program.cs └── SimpleImplementation │ ├── ClientObject.cs │ ├── FlyWeight.cs │ └── FlyWeightPointer.cs ├── Interpreter ├── Context │ └── TokenReader.cs ├── Expression │ ├── AddExpression.cs │ ├── IExpression.cs │ ├── NumberExpression.cs │ └── SubtractExpression.cs ├── Interpreter.csproj └── Program.cs ├── Iterator ├── Aggregate │ ├── Aggregate.cs │ └── ConcreteAggregate.cs ├── BuiltIn │ ├── MyCollection.cs │ └── MyCollectionEnumerator.cs ├── Iterator.csproj ├── Iterator │ ├── ConcreteIterator.cs │ └── Iterator.cs └── Program.cs ├── LICENSE ├── Mediator ├── Colleague │ ├── IUser.cs │ ├── User.cs │ └── VipUser.cs ├── Mediator.csproj ├── Mediator │ ├── ChatMediator.cs │ └── IChatMediator.cs └── Program.cs ├── Memento ├── Memento.cs ├── Memento.csproj ├── OriginalObject.cs └── Program.cs ├── NullObject ├── Animal.cs ├── Dog.cs ├── IAnimal.cs ├── NullObject.csproj └── Program.cs ├── Observer ├── BuiltInObserver │ ├── Observer │ │ ├── GermanyWeatherStation.cs │ │ ├── IranWeatherStation.cs │ │ └── UnitedStateWeatherStation.cs │ └── Subject │ │ ├── WeatherEventArgs.cs │ │ └── WeatherReport.cs ├── Observer.csproj ├── ObserverObjects │ ├── ConcreteObserver.cs │ └── Observer.cs ├── Program.cs └── SubjectObjects │ ├── ConcreteSubject.cs │ └── Subject.cs ├── Prototype ├── AbstractPrototype │ └── IPerson.cs ├── ConcretePrototype │ ├── Dick.cs │ ├── Harry.cs │ └── Tom.cs ├── Program.cs ├── Prototype.csproj └── PrototypeUsage │ └── Factory.cs ├── Proxy ├── ActualObjects │ ├── Car.cs │ ├── Driver.cs │ └── ICar.cs ├── Program.cs ├── Proxy.csproj └── Proxy │ └── ProxyCar.cs ├── README.md ├── RepositoryAndUnitOfWork ├── DomainModels │ ├── ApplicationUser.cs │ ├── Article.cs │ ├── ArticleArticleTag.cs │ ├── ArticleComment.cs │ ├── ArticleRating.cs │ ├── ArticleTag.cs │ ├── Contact.cs │ ├── Portfolio.cs │ ├── SiteOrder.cs │ └── SlideShow.cs ├── ORM │ └── FreelancerBlogContext.cs ├── Program.cs ├── Repositories │ ├── ArticleRepository.cs │ ├── ContactRepository.cs │ ├── PortfolioRepository.cs │ ├── SiteOrderRepository.cs │ ├── SlideShowRepository.cs │ └── UserRepository.cs ├── RepositoryAndUnitOfWork.csproj ├── RepositoryInterfaces │ ├── IArticleRepository.cs │ ├── IContactRepository.cs │ ├── IPortfolioRepository.cs │ ├── IRepository.cs │ ├── ISiteOrderRepository.cs │ ├── ISlideShowRepository.cs │ └── IUserRepository.cs └── UnitOfWorkParts │ ├── IUnitOfWork.cs │ └── UnitOfWork.cs ├── Singleton ├── Program.cs ├── Singleton.csproj ├── SingletonLazy.cs ├── SingletonWithLock.cs └── SingletonWithoutLock.cs ├── Specification ├── BaseSpecification.cs ├── Basket.cs ├── BasketWithItemsSpecification.cs ├── ISpecification.cs ├── Program.cs ├── Repository.cs └── Specification.csproj ├── State ├── Legacy │ ├── GumballMachine.cs │ └── State.cs ├── Program.cs ├── Refactored │ ├── Abstraction │ │ └── IState.cs │ ├── StateMachineContext │ │ └── GumballMachine.cs │ └── VariousStates │ │ ├── HasQuarterState.cs │ │ ├── NoQuarterState.cs │ │ ├── SoldOutState.cs │ │ ├── SoldState.cs │ │ └── WinnerState.cs └── State.csproj ├── Strategy ├── Anbstraction │ └── IDataReader.cs ├── Implementations │ ├── JsonDataReader.cs │ ├── SqlDataReader.cs │ └── XmlDataReader.cs ├── Program.cs └── Strategy.csproj ├── TemplateMethod ├── AuditExample │ ├── Abstraction │ │ ├── IMessageAuditor.cs │ │ └── MessageProcessor.cs │ ├── CancelOrderMessageProcessor.cs │ └── MoreInfo.txt ├── DrinkExample │ ├── Abstraction │ │ └── Beverage.cs │ └── Implementations │ │ ├── Coffee.cs │ │ └── Tea.cs ├── Program.cs └── TemplateMethod.csproj └── Visitor ├── Elements ├── BoldText.cs ├── Hyperlink.cs └── PlainText.cs ├── ObjectStructure ├── Document.cs └── DocumentPart.cs ├── OldImplementation └── OldImplementation.cs ├── Program.cs ├── Visitor.csproj └── Visitors ├── HtmlVisitor.cs ├── IVisitor.cs └── LatexVisitor.cs /--wait: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamidMosalla/CSharpDesignPatterns/6de14a00bc429bcbe2c6bd35199375f7d9863c5a/--wait -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | *.appx 187 | 188 | # Visual Studio cache files 189 | # files ending in .cache can be ignored 190 | *.[Cc]ache 191 | # but keep track of directories ending in .cache 192 | !*.[Cc]ache/ 193 | 194 | # Others 195 | ClientBin/ 196 | ~$* 197 | *~ 198 | *.dbmdl 199 | *.dbproj.schemaview 200 | *.jfm 201 | *.pfx 202 | *.publishsettings 203 | orleans.codegen.cs 204 | 205 | # Since there are multiple workflows, uncomment next line to ignore bower_components 206 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 207 | #bower_components/ 208 | 209 | # RIA/Silverlight projects 210 | Generated_Code/ 211 | 212 | # Backup & report files from converting an old project file 213 | # to a newer Visual Studio version. Backup files are not needed, 214 | # because we have git ;-) 215 | _UpgradeReport_Files/ 216 | Backup*/ 217 | UpgradeLog*.XML 218 | UpgradeLog*.htm 219 | 220 | # SQL Server files 221 | *.mdf 222 | *.ldf 223 | *.ndf 224 | 225 | # Business Intelligence projects 226 | *.rdl.data 227 | *.bim.layout 228 | *.bim_*.settings 229 | 230 | # Microsoft Fakes 231 | FakesAssemblies/ 232 | 233 | # GhostDoc plugin setting file 234 | *.GhostDoc.xml 235 | 236 | # Node.js Tools for Visual Studio 237 | .ntvs_analysis.dat 238 | node_modules/ 239 | 240 | # Typescript v1 declaration files 241 | typings/ 242 | 243 | # Visual Studio 6 build log 244 | *.plg 245 | 246 | # Visual Studio 6 workspace options file 247 | *.opt 248 | 249 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 250 | *.vbw 251 | 252 | # Visual Studio LightSwitch build output 253 | **/*.HTMLClient/GeneratedArtifacts 254 | **/*.DesktopClient/GeneratedArtifacts 255 | **/*.DesktopClient/ModelManifest.xml 256 | **/*.Server/GeneratedArtifacts 257 | **/*.Server/ModelManifest.xml 258 | _Pvt_Extensions 259 | 260 | # Paket dependency manager 261 | .paket/paket.exe 262 | paket-files/ 263 | 264 | # FAKE - F# Make 265 | .fake/ 266 | 267 | # JetBrains Rider 268 | .idea/ 269 | *.sln.iml 270 | 271 | # CodeRush 272 | .cr/ 273 | 274 | # Python Tools for Visual Studio (PTVS) 275 | __pycache__/ 276 | *.pyc 277 | 278 | # Cake - Uncomment if you are using it 279 | # tools/** 280 | # !tools/packages.config 281 | 282 | # Telerik's JustMock configuration file 283 | *.jmconfig 284 | 285 | # BizTalk build output 286 | *.btp.cs 287 | *.btm.cs 288 | *.odx.cs 289 | *.xsd.cs -------------------------------------------------------------------------------- /AbstractFactory/AbstractFactory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/AbstractCars/FamilyCar.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactory.Cars.AbstractCars 2 | { 3 | public abstract class FamilyCar 4 | { 5 | public abstract void Speed(SportsCar abstractFamilyCar); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/AbstractCars/SportsCar.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactory.Cars.AbstractCars 2 | { 3 | public abstract class SportsCar 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/ConcreteCars/AudiFamilyCar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AbstractFactory.Cars.AbstractCars; 3 | 4 | namespace AbstractFactory.Cars.ConcreteCars 5 | { 6 | class AudiFamilyCar : FamilyCar 7 | { 8 | public override void Speed(SportsCar abstractSportsCar) 9 | { 10 | Console.WriteLine(GetType().Name + " is slower than " + abstractSportsCar.GetType().Name); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/ConcreteCars/AudiSportsCar.cs: -------------------------------------------------------------------------------- 1 | using AbstractFactory.Cars.AbstractCars; 2 | 3 | namespace AbstractFactory.Cars.ConcreteCars 4 | { 5 | class AudiSportsCar : SportsCar 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/ConcreteCars/MercedesFamilyCar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AbstractFactory.Cars.AbstractCars; 3 | 4 | namespace AbstractFactory.Cars.ConcreteCars 5 | { 6 | class MercedesFamilyCar : FamilyCar 7 | { 8 | public override void Speed(SportsCar abstractSportsCar) 9 | { 10 | Console.WriteLine(GetType().Name + " is slower than " 11 | + abstractSportsCar.GetType().Name); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AbstractFactory/Cars/ConcreteCars/MercedesSportsCar.cs: -------------------------------------------------------------------------------- 1 | using AbstractFactory.Cars.AbstractCars; 2 | 3 | namespace AbstractFactory.Cars.ConcreteCars 4 | { 5 | class MercedesSportsCar : SportsCar 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /AbstractFactory/Client/Driver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using AbstractFactory.Cars; 5 | using AbstractFactory.Cars.AbstractCars; 6 | using AbstractFactory.Factory; 7 | using AbstractFactory.Factory.AnstractFactory; 8 | 9 | namespace AbstractFactory.Client 10 | { 11 | public class Driver 12 | { 13 | private SportsCar _sportsCar; 14 | private FamilyCar _familyCar; 15 | 16 | public Driver(CarFactory carFactory) 17 | { 18 | _sportsCar = carFactory.CreateSportsCar(); 19 | _familyCar = carFactory.CreateFamilyCar(); 20 | } 21 | 22 | public void CompareSpeed() 23 | { 24 | _familyCar.Speed(_sportsCar); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AbstractFactory/Factory/AnstractFactory/CarFactory.cs: -------------------------------------------------------------------------------- 1 | using AbstractFactory.Cars.AbstractCars; 2 | 3 | namespace AbstractFactory.Factory.AnstractFactory 4 | { 5 | public abstract class CarFactory 6 | { 7 | public abstract SportsCar CreateSportsCar(); 8 | public abstract FamilyCar CreateFamilyCar(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /AbstractFactory/Factory/ConcreteFactory/AudiFactory.cs: -------------------------------------------------------------------------------- 1 | using AbstractFactory.Cars; 2 | using AbstractFactory.Cars.AbstractCars; 3 | using AbstractFactory.Cars.ConcreteCars; 4 | using AbstractFactory.Factory.AnstractFactory; 5 | 6 | namespace AbstractFactory.Factory.ConcreteFactory 7 | { 8 | public class AudiFactory : CarFactory 9 | { 10 | public override SportsCar CreateSportsCar() 11 | { 12 | return new AudiSportsCar(); 13 | } 14 | 15 | public override FamilyCar CreateFamilyCar() 16 | { 17 | return new AudiFamilyCar(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AbstractFactory/Factory/ConcreteFactory/MercedesFactory.cs: -------------------------------------------------------------------------------- 1 | using AbstractFactory.Cars.AbstractCars; 2 | using AbstractFactory.Cars.ConcreteCars; 3 | using AbstractFactory.Factory.AnstractFactory; 4 | 5 | namespace AbstractFactory.Factory.ConcreteFactory 6 | { 7 | public class MercedesFactory : CarFactory 8 | { 9 | public override SportsCar CreateSportsCar() 10 | { 11 | return new MercedesSportsCar(); 12 | } 13 | 14 | public override FamilyCar CreateFamilyCar() 15 | { 16 | return new MercedesFamilyCar(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /AbstractFactory/Factory/GenericFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace AbstractFactory.Factory 6 | { 7 | public class GenericFactory where T : new() 8 | { 9 | public T CreateObject() 10 | { 11 | return new T(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AbstractFactory/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AbstractFactory.Cars; 3 | using AbstractFactory.Cars.ConcreteCars; 4 | using AbstractFactory.Client; 5 | using AbstractFactory.Factory; 6 | using AbstractFactory.Factory.AnstractFactory; 7 | using AbstractFactory.Factory.ConcreteFactory; 8 | 9 | namespace AbstractFactory 10 | { 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | 16 | /* 17 | More info: https://en.wikipedia.org/wiki/Abstract_factory_pattern 18 | https://csharpdesignpatterns.codeplex.com/wikipage?title=Abstract%20Factory%20Pattern&referringTitle=Home 19 | The Abstract Factory design pattern solves problems like: 20 | 21 | How can an application be independent of how its objects are created? 22 | How can a class be independent of how the objects it requires are created? 23 | How can families of related or dependent objects be created? 24 | 25 | Creating objects directly within the class that requires the objects is inflexible because it commits 26 | the class to particular objects and makes it impossible to change the instantiation later independently 27 | from (without having to change) the class. It stops the class from being reusable if other objects are required, 28 | and it makes the class hard to test because real objects can't be replaced with mock objects. 29 | */ 30 | 31 | 32 | CarFactory audiFactory = new AudiFactory(); 33 | Driver driver1 = new Driver(audiFactory); 34 | driver1.CompareSpeed(); 35 | 36 | CarFactory mercedesFactory = new MercedesFactory(); 37 | Driver driver2 = new Driver(mercedesFactory); 38 | driver2.CompareSpeed(); 39 | 40 | 41 | var factory = new GenericFactory(); 42 | var mercedesSportsCar = factory.CreateObject(); 43 | Console.WriteLine(mercedesSportsCar.GetType().ToString()); 44 | 45 | Console.ReadKey(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Adapter/Adapted/DatabaseHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Adapter.Adapted 4 | { 5 | class DatabaseHelper 6 | { 7 | public void QueryForChanges() 8 | { 9 | Console.WriteLine("Database queried."); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Adapter/Adapted/WebSiteScanner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Adapter.Adapted 4 | { 5 | class WebSiteScanner 6 | { 7 | public void Scan() 8 | { 9 | Console.WriteLine("Web sites scanned."); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Adapter/Adapted/XmlFileLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Adapter.Adapted 4 | { 5 | class XmlFileLoader 6 | { 7 | public void LoadXML() 8 | { 9 | Console.WriteLine("Xml files loaded."); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Adapter/Adapter.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Adapter/Adapter/Connector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Adapter.Adapter 6 | { 7 | public abstract class Connector 8 | { 9 | public abstract void GetData(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Adapter/Adapter/DatabaseConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Adapter.Adapted; 5 | 6 | namespace Adapter.Adapter 7 | { 8 | public class DatabaseConnector : Connector 9 | { 10 | public override void GetData() 11 | { 12 | var databaseHelper = new DatabaseHelper(); 13 | databaseHelper.QueryForChanges(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Adapter/Adapter/HttpStreamConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Adapter.Adapted; 5 | 6 | namespace Adapter.Adapter 7 | { 8 | public class HttpStreamConnector : Connector 9 | { 10 | public override void GetData() 11 | { 12 | var websiteScanner = new WebSiteScanner(); 13 | websiteScanner.Scan(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Adapter/Adapter/XmlFileConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Adapter.Adapted; 5 | 6 | namespace Adapter.Adapter 7 | { 8 | public class XmlFileConnector : Connector 9 | { 10 | public override void GetData() 11 | { 12 | var xmlfileLoader = new XmlFileLoader(); 13 | xmlfileLoader.LoadXML(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Adapter/Client/TradingDataImporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Adapter.Adapter; 5 | 6 | namespace Adapter.Client 7 | { 8 | class TradingDataImporter 9 | { 10 | public void ImportData(Connector connector) 11 | { 12 | connector.GetData(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Adapter/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Adapter.Adapter; 3 | using Adapter.Client; 4 | 5 | namespace Adapter 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | /* 13 | * The Adapter design pattern solves problems like: 14 | How can a class be reused that does not have an interface that a client requires? 15 | How can classes that have incompatible interfaces work together? 16 | How can an alternative interface be provided for a class? 17 | 18 | Often an (already existing) class can't be reused only 19 | because its interface doesn't conform to the interface clients require. 20 | More info: https://csharpdesignpatterns.codeplex.com/wikipage?title=Adapter%20Pattern&referringTitle=Home 21 | */ 22 | 23 | 24 | var tradingdataImporter = new TradingDataImporter(); 25 | 26 | Connector databaseConnector = new DatabaseConnector(); 27 | tradingdataImporter.ImportData(databaseConnector); 28 | 29 | Connector xmlfileConnector = new XmlFileConnector(); 30 | tradingdataImporter.ImportData(xmlfileConnector); 31 | 32 | Connector httpstreamConnector = new HttpStreamConnector(); 33 | tradingdataImporter.ImportData(httpstreamConnector); 34 | 35 | Console.ReadKey(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Bridge/Abstraction/Repository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Bridge.ImplementorAbstract; 5 | 6 | namespace Bridge.Abstraction 7 | { 8 | public abstract class Repository 9 | { 10 | public abstract void AddObject(DataObject dataObject); 11 | public abstract void CopyObject(DataObject dataObject); 12 | public abstract void RemoveObject(DataObject dataObject); 13 | 14 | public void SaveChanges() 15 | { 16 | Console.WriteLine("Changes were saved"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Bridge/AbstractionRefined/ClientRepository.cs: -------------------------------------------------------------------------------- 1 | using Bridge.Abstraction; 2 | using Bridge.ImplementorAbstract; 3 | 4 | namespace Bridge.AbstractionRefined 5 | { 6 | public class ClientRepository : Repository 7 | { 8 | public override void AddObject(DataObject dataObject) 9 | { 10 | // Do repository specific work 11 | dataObject.Register(); 12 | } 13 | 14 | public override void CopyObject(DataObject dataObject) 15 | { 16 | // Do repository specific work 17 | dataObject.Copy(); 18 | } 19 | 20 | public override void RemoveObject(DataObject dataObject) 21 | { 22 | // Do repository specific work 23 | dataObject.Delete(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bridge/AbstractionRefined/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Bridge.Abstraction; 2 | using Bridge.ImplementorAbstract; 3 | 4 | namespace Bridge.AbstractionRefined 5 | { 6 | public class ProductRepository : Repository 7 | { 8 | public override void AddObject(DataObject dataObject) 9 | { 10 | // Do repository specific work 11 | dataObject.Register(); 12 | } 13 | 14 | public override void CopyObject(DataObject dataObject) 15 | { 16 | // Do repository specific work 17 | dataObject.Copy(); 18 | } 19 | 20 | public override void RemoveObject(DataObject dataObject) 21 | { 22 | // Do repository specific work 23 | dataObject.Delete(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bridge/Bridge.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Bridge/ImplementorAbstract/DataObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Bridge.ImplementorAbstract 6 | { 7 | public abstract class DataObject 8 | { 9 | public abstract void Register(); 10 | public abstract DataObject Copy(); 11 | public abstract void Delete(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Bridge/ImplementorConcrete/ClientDataObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Bridge.ImplementorAbstract; 5 | 6 | namespace Bridge.ImplementorConcrete 7 | { 8 | public class ClientDataObject : DataObject 9 | { 10 | public override void Register() 11 | { 12 | Console.WriteLine("ClientDataObject was registered"); 13 | } 14 | 15 | public override DataObject Copy() 16 | { 17 | Console.WriteLine("ClientDataObject was copied"); 18 | return new ClientDataObject(); 19 | } 20 | 21 | public override void Delete() 22 | { 23 | Console.WriteLine("ClientDataObject was deleted"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bridge/ImplementorConcrete/ProductDataObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Bridge.ImplementorAbstract; 5 | 6 | namespace Bridge.ImplementorConcrete 7 | { 8 | public class ProductDataObject : DataObject 9 | { 10 | public override void Register() 11 | { 12 | Console.WriteLine("ProductDataObject was registered"); 13 | } 14 | 15 | public override DataObject Copy() 16 | { 17 | Console.WriteLine("ProductDataObject was copied"); 18 | return new ProductDataObject(); 19 | } 20 | 21 | public override void Delete() 22 | { 23 | Console.WriteLine("ProductDataObject was deleted"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bridge/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Bridge.AbstractionRefined; 3 | using Bridge.ImplementorConcrete; 4 | 5 | namespace Bridge 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | /* 13 | * https://en.wikipedia.org/wiki/Bridge_pattern 14 | What problems can the Bridge design pattern solve? 15 | An abstraction and its implementation should be defined and extended independently from each other. 16 | A compile-time binding between an abstraction and its implementation should be avoided so that an implementation can be selected at run-time. 17 | 18 | When using subclassing, different subclasses implement an abstract class in different ways. 19 | But an implementation is bound to the abstraction at compile-time and can't be changed at run-time. 20 | */ 21 | 22 | var clientRepository = new ClientRepository(); 23 | var clientDataObject = new ClientDataObject(); 24 | 25 | clientRepository.AddObject(clientDataObject); 26 | clientRepository.SaveChanges(); 27 | 28 | clientRepository.CopyObject(clientDataObject); 29 | clientRepository.RemoveObject(clientDataObject); 30 | clientRepository.SaveChanges(); 31 | 32 | Console.WriteLine("==============================================================="); 33 | 34 | var productRepository = new ProductRepository(); 35 | var productDataObject = new ProductDataObject(); 36 | 37 | productRepository.AddObject(productDataObject); 38 | clientRepository.SaveChanges(); 39 | 40 | productRepository.CopyObject(productDataObject); 41 | productRepository.RemoveObject(productDataObject); 42 | productRepository.SaveChanges(); 43 | 44 | 45 | 46 | 47 | Console.ReadKey(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Builder/Builder.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Builder/Builder/AbstractBuilder/IPhoneBuilder.cs: -------------------------------------------------------------------------------- 1 | using Builder.Builder.Object; 2 | 3 | namespace Builder.Builder.AbstractBuilder 4 | { 5 | interface IPhoneBuilder 6 | { 7 | void BuildScreen(); 8 | void BuildBattery(); 9 | void BuildOS(); 10 | void BuildStylus(); 11 | MobilePhone Construct(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Builder/Builder/ConcreteBuilder/AndroidPhoneBuilder.cs: -------------------------------------------------------------------------------- 1 | using Builder.Builder.AbstractBuilder; 2 | using Builder.Builder.Object; 3 | using Builder.Builder.Parts; 4 | 5 | namespace Builder.Builder.ConcreteBuilder 6 | { 7 | class AndroidPhoneBuilder : IPhoneBuilder 8 | { 9 | MobilePhone phone; 10 | 11 | public AndroidPhoneBuilder() 12 | { 13 | phone = new MobilePhone("Android Phone"); 14 | } 15 | 16 | public void BuildScreen() 17 | { 18 | phone.PhoneScreen = ScreenType.GorillaGlass; 19 | } 20 | 21 | public void BuildBattery() 22 | { 23 | phone.PhoneBatteryCapacity = BatteryCapacity.ThousandMa; 24 | } 25 | 26 | public void BuildOS() 27 | { 28 | phone.PhoneOS = Builder.Parts.Os.Android; 29 | } 30 | 31 | public void BuildStylus() 32 | { 33 | phone.PhoneStylus = Stylus.Yes; 34 | } 35 | 36 | //finally construct the final phone 37 | public MobilePhone Construct() 38 | { 39 | return phone; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Builder/Builder/ConcreteBuilder/WindowsPhoneBuilder.cs: -------------------------------------------------------------------------------- 1 | using Builder.Builder.AbstractBuilder; 2 | using Builder.Builder.Object; 3 | using Builder.Builder.Parts; 4 | 5 | namespace Builder.Builder.ConcreteBuilder 6 | { 7 | class WindowsPhoneBuilder : IPhoneBuilder 8 | { 9 | MobilePhone phone; 10 | 11 | public WindowsPhoneBuilder() 12 | { 13 | phone = new MobilePhone("Windows Phone"); 14 | } 15 | 16 | public void BuildScreen() 17 | { 18 | phone.PhoneScreen = ScreenType.Touch; 19 | } 20 | 21 | public void BuildBattery() 22 | { 23 | phone.PhoneBatteryCapacity = BatteryCapacity.TwoThousandMa; 24 | } 25 | 26 | public void BuildOS() 27 | { 28 | phone.PhoneOS = Builder.Parts.Os.WindowsPhone; 29 | } 30 | 31 | public void BuildStylus() 32 | { 33 | phone.PhoneStylus = Stylus.No; 34 | } 35 | 36 | public MobilePhone Construct() 37 | { 38 | return phone; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Builder/Builder/Director/Manufacturer.cs: -------------------------------------------------------------------------------- 1 | using Builder.Builder.AbstractBuilder; 2 | using Builder.Builder.Object; 3 | 4 | namespace Builder.Builder.Director 5 | { 6 | class Manufacturer 7 | { 8 | public MobilePhone Construct(IPhoneBuilder phoneBuilder) 9 | { 10 | phoneBuilder.BuildBattery(); 11 | phoneBuilder.BuildOS(); 12 | phoneBuilder.BuildScreen(); 13 | phoneBuilder.BuildStylus(); 14 | return phoneBuilder.Construct(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Builder/Builder/Object/MobilePhone.cs: -------------------------------------------------------------------------------- 1 | using Builder.Builder.Parts; 2 | 3 | namespace Builder.Builder.Object 4 | { 5 | class MobilePhone 6 | { 7 | public MobilePhone(string name) 8 | { 9 | PhoneName = name; 10 | } 11 | 12 | public string PhoneName { get; } 13 | 14 | public ScreenType PhoneScreen { get; set; } 15 | 16 | public BatteryCapacity PhoneBatteryCapacity { get; set; } 17 | 18 | public Os PhoneOS { get; set; } 19 | 20 | public Stylus PhoneStylus { get; set; } 21 | 22 | public override string ToString() 23 | { 24 | return string.Format("Name: {0}\nScreen: {1}\nBattery {2}\nOS: {3}\nStylus: {4}", PhoneName, PhoneScreen, PhoneBatteryCapacity, PhoneOS, PhoneStylus); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Builder/Builder/Parts/BatteryCapacity.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.Builder.Parts 2 | { 3 | public enum BatteryCapacity 4 | { 5 | ThousandMa = 1000, 6 | TwoThousandMa = 2000, 7 | ThreeThousandMa = 3000 8 | } 9 | } -------------------------------------------------------------------------------- /Builder/Builder/Parts/Os.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.Builder.Parts 2 | { 3 | public enum Os 4 | { 5 | Android, 6 | WindowsMobile, 7 | WindowsPhone, 8 | Symbian 9 | }; 10 | } -------------------------------------------------------------------------------- /Builder/Builder/Parts/ScreenType.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.Builder.Parts 2 | { 3 | public enum ScreenType 4 | { 5 | Touch, 6 | GorillaGlass, 7 | NonTouch 8 | }; 9 | } -------------------------------------------------------------------------------- /Builder/Builder/Parts/Stylus.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.Builder.Parts 2 | { 3 | public enum Stylus 4 | { 5 | Yes, 6 | No 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /Builder/FluentBuilder/House.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.FluentBuilder 2 | { 3 | internal class House 4 | { 5 | public long Area { set; get; } 6 | public int NumberOfRooms { get; set; } 7 | public bool HasGarage { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Builder/FluentBuilder/HouseBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Builder.FluentBuilder 6 | { 7 | class HouseBuilder : IHouseBuilder 8 | { 9 | private House _house; 10 | 11 | public HouseBuilder() 12 | { 13 | _house = new House(); 14 | } 15 | 16 | public HouseBuilder Area(int area) 17 | { 18 | _house.Area = area; 19 | return this; 20 | } 21 | 22 | public HouseBuilder NumberOfRooms(int numberOfRooms) 23 | { 24 | _house.NumberOfRooms = numberOfRooms; 25 | return this; 26 | } 27 | 28 | public HouseBuilder HasGarage(bool hasGarage) 29 | { 30 | _house.HasGarage = hasGarage; 31 | return this; 32 | } 33 | 34 | public House Build() 35 | { 36 | House result = _house; 37 | _house = null; //prevent multiple invocations of Build() 38 | return result; 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Builder/FluentBuilder/IHouseBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Builder.FluentBuilder 2 | { 3 | internal interface IHouseBuilder 4 | { 5 | House Build(); 6 | } 7 | } -------------------------------------------------------------------------------- /Builder/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Builder.Builder.AbstractBuilder; 3 | using Builder.Builder.ConcreteBuilder; 4 | using Builder.Builder.Director; 5 | using Builder.FluentBuilder; 6 | 7 | namespace Builder 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | var house = new HouseBuilder() 14 | .Area(500) 15 | .NumberOfRooms(4) 16 | .HasGarage(true) 17 | .Build(); 18 | 19 | 20 | //More info: https://www.codeproject.com/Articles/470476/Understanding-and-Implementing-Builder-Pattern-in 21 | //Slightly modified version of above link 22 | 23 | // Lets create the Director first 24 | var manufacturer = new Manufacturer(); 25 | 26 | // Now let us create an android phone 27 | IPhoneBuilder androidPhoneBuilder = new AndroidPhoneBuilder(); 28 | var androidPhone = manufacturer.Construct(androidPhoneBuilder); 29 | 30 | // Now let us create a Windows Phone 31 | IPhoneBuilder windowsPhoneBuilder = new WindowsPhoneBuilder(); 32 | var windowsPhone = manufacturer.Construct(windowsPhoneBuilder); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ChainOfResponsibility/Abstrations/Handler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ChainOfResponsibility.Abstrations 6 | { 7 | abstract class Handler 8 | { 9 | protected Handler successor; 10 | 11 | public void SetSuccessor(Handler successor) 12 | { 13 | this.successor = successor; 14 | } 15 | 16 | public abstract void HandleRequest(int request); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ChainOfResponsibility/ChainOfResponsibility.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ChainOfResponsibility/Implementations/ConcreteHandler1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ChainOfResponsibility.Abstrations; 5 | 6 | namespace ChainOfResponsibility.Implementations 7 | { 8 | class ConcreteHandler1 : Handler 9 | { 10 | public override void HandleRequest(int request) 11 | { 12 | if (request >= 0 && request < 10) 13 | { 14 | Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); 15 | } 16 | else if (successor != null) 17 | { 18 | successor.HandleRequest(request); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ChainOfResponsibility/Implementations/ConcreteHandler2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ChainOfResponsibility.Abstrations; 3 | 4 | namespace ChainOfResponsibility.Implementations 5 | { 6 | internal class ConcreteHandler2 : Handler 7 | { 8 | public override void HandleRequest(int request) 9 | { 10 | if (request >= 10 && request < 20) 11 | { 12 | Console.WriteLine("{0} handled request {1}", GetType().Name, request); 13 | } 14 | else if (successor != null) 15 | { 16 | successor.HandleRequest(request); 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /ChainOfResponsibility/Implementations/ConcreteHandler3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ChainOfResponsibility.Abstrations; 5 | 6 | namespace ChainOfResponsibility.Implementations 7 | { 8 | class ConcreteHandler3 : Handler 9 | { 10 | public override void HandleRequest(int request) 11 | { 12 | if (request >= 20 && request < 30) 13 | { 14 | Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); 15 | } 16 | 17 | else if (successor != null) 18 | { 19 | successor.HandleRequest(request); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ChainOfResponsibility/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ChainOfResponsibility.Abstrations; 3 | using ChainOfResponsibility.Implementations; 4 | 5 | namespace ChainOfResponsibility 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | /* 13 | * More info: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern 14 | * http://www.dofactory.com/net/chain-of-responsibility-design-pattern 15 | What problems can the Chain of Responsibility design pattern solve? 16 | Coupling the sender of a request to its receiver should be avoided. 17 | It should be possible that more than one receiver can handle a request. 18 | 19 | Implementing a request directly within the class that sends the request is inflexible because it couples the class to a particular receiver and makes it impossible 20 | to support multiple receivers. 21 | */ 22 | 23 | 24 | // Setup Chain of Responsibility 25 | Handler h1 = new ConcreteHandler1(); 26 | Handler h2 = new ConcreteHandler2(); 27 | Handler h3 = new ConcreteHandler3(); 28 | h1.SetSuccessor(h2); 29 | h2.SetSuccessor(h3); 30 | 31 | // Generate and process request 32 | int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; 33 | 34 | foreach (int request in requests) 35 | { 36 | h1.HandleRequest(request); 37 | } 38 | 39 | Console.ReadKey(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Command/Client/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Command.CommandInvoker; 3 | using Command.Commands; 4 | using Command.Receiver; 5 | 6 | namespace Command.Client 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | 13 | /* 14 | More info: https://en.wikipedia.org/wiki/Command_pattern 15 | What problems can the Command design pattern solve? 16 | 17 | Coupling the invoker of a request to a particular request should be avoided. 18 | That is, hard-wired requests should be avoided. 19 | It should be possible to configure an object (that invokes a request) with a request. 20 | 21 | Implementing (hard-wiring) a request directly into a class is inflexible because 22 | it couples the class to a particular request at compile-time, 23 | which makes it impossible to specify a request at run-time. 24 | */ 25 | 26 | string argument = Console.ReadLine(); 27 | 28 | ISwitchable lamp = new Light(); 29 | 30 | //Pass reference to the lamp instance to each command 31 | ICommand switchClose = new CloseSwitchCommand(lamp); 32 | ICommand switchOpen = new OpenSwitchCommand(lamp); 33 | 34 | //Pass reference to instances of the Command objects to the switch 35 | Switch @switch = new Switch(switchClose, switchOpen); 36 | 37 | if (argument == "ON") 38 | { 39 | // Switch (the Invoker) will invoke Execute() on the command object. 40 | @switch.Close(); 41 | } 42 | else if (argument == "OFF") 43 | { 44 | //Switch (the Invoker) will invoke the Execute() on the command object. 45 | @switch.Open(); 46 | } 47 | else 48 | { 49 | Console.WriteLine("Argument \"ON\" or \"OFF\" is required."); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Command/Command.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Command/CommandInvoker/Switch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Command.Commands; 5 | 6 | namespace Command.CommandInvoker 7 | { 8 | public class Switch 9 | { 10 | readonly ICommand _closedCommand; 11 | readonly ICommand _openedCommand; 12 | 13 | public Switch(ICommand closedCommand, ICommand openedCommand) 14 | { 15 | this._closedCommand = closedCommand; 16 | this._openedCommand = openedCommand; 17 | } 18 | 19 | //close the circuit/power on 20 | public void Close() 21 | { 22 | this._closedCommand.Execute(); 23 | } 24 | 25 | //open the circuit/power off 26 | public void Open() 27 | { 28 | this._openedCommand.Execute(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Command/Commands/CloseSwitchCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Input; 5 | using Command.Receiver; 6 | 7 | namespace Command.Commands 8 | { 9 | public class CloseSwitchCommand : ICommand 10 | { 11 | private ISwitchable _switchable; 12 | 13 | public CloseSwitchCommand(ISwitchable switchable) 14 | { 15 | _switchable = switchable; 16 | } 17 | 18 | public void Execute() 19 | { 20 | _switchable.PowerOn(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Command/Commands/ICommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Command.Commands 6 | { 7 | public interface ICommand 8 | { 9 | void Execute(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Command/Commands/OpenSwitchCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Command.Receiver; 5 | 6 | namespace Command.Commands 7 | { 8 | public class OpenSwitchCommand : ICommand 9 | { 10 | private ISwitchable _switchable; 11 | 12 | public OpenSwitchCommand(ISwitchable switchable) 13 | { 14 | _switchable = switchable; 15 | } 16 | 17 | public void Execute() 18 | { 19 | _switchable.PowerOff(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Command/Receiver/ISwitchable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Command.Receiver 6 | { 7 | public interface ISwitchable 8 | { 9 | void PowerOn(); 10 | void PowerOff(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Command/Receiver/Light.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Command.Receiver 6 | { 7 | public class Light : ISwitchable 8 | { 9 | public void PowerOn() 10 | { 11 | Console.WriteLine("The light is on"); 12 | } 13 | 14 | public void PowerOff() 15 | { 16 | Console.WriteLine("The light is off"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Composite/ComponentObject/CompositeGraphic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Composite.ComponentObject 5 | { 6 | internal class CompositeGraphic : IGraphic 7 | { 8 | private string _name; 9 | private readonly List _graphics = new List(); 10 | 11 | public CompositeGraphic(string name) 12 | { 13 | _name = name; 14 | } 15 | 16 | public void Add(IGraphic component) 17 | { 18 | _graphics.Add(component); 19 | } 20 | 21 | public void AddRange(params IGraphic[] graphic) 22 | { 23 | _graphics.AddRange(graphic); 24 | } 25 | 26 | public void Remove(IGraphic component) 27 | { 28 | _graphics.Remove(component); 29 | } 30 | 31 | public void Display(int depth) 32 | { 33 | Console.WriteLine(new string('-', depth) + _name); 34 | 35 | foreach (var component in _graphics) 36 | { 37 | component.Display(depth + 2); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Composite/ComponentObject/IGraphic.cs: -------------------------------------------------------------------------------- 1 | namespace Composite.ComponentObject 2 | { 3 | public interface IGraphic 4 | { 5 | void Display(int depth); 6 | } 7 | } -------------------------------------------------------------------------------- /Composite/Composite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Composite/LeafObject/Leaf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Composite.ComponentObject; 3 | 4 | namespace Composite.LeafObject 5 | { 6 | internal class Leaf : IGraphic 7 | { 8 | private readonly string _name; 9 | 10 | public Leaf(string name) 11 | { 12 | _name = name; 13 | } 14 | 15 | public void Display(int depth) 16 | { 17 | Console.WriteLine(new string('-', depth) + _name); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Composite/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Composite.LeafObject; 3 | using Composite.ComponentObject; 4 | 5 | namespace Composite 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | /* 12 | More info: https://en.wikipedia.org/wiki/Composite_pattern 13 | What problems can the Composite design pattern solve? 14 | 15 | A part-whole hierarchy should be represented so that clients can treat part and whole objects uniformly. 16 | A part-whole hierarchy should be represented as tree structure. 17 | 18 | When defining (1) Part objects and (2) Whole objects that act as containers for Part objects, 19 | clients must treat them separately, which complicates client code. 20 | */ 21 | 22 | CompositeGraphic root = new CompositeGraphic("root"); 23 | root.Add(new Leaf("Leaf A")); 24 | root.Add(new Leaf("Leaf B")); 25 | 26 | CompositeGraphic comp = new CompositeGraphic("Composite X"); 27 | comp.AddRange(new Leaf("Leaf XA"), new Leaf("Leaf XB")); 28 | 29 | root.Add(comp); 30 | root.Add(new Leaf("Leaf C")); 31 | 32 | 33 | Leaf leaf = new Leaf("Leaf D"); 34 | root.Add(leaf); 35 | root.Remove(leaf); 36 | 37 | root.Display(1); 38 | 39 | Console.ReadKey(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Decorator/Component/ICoffee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Decorator.Component 6 | { 7 | public interface ICoffee 8 | { 9 | double GetCost(); 10 | string GetIngredients(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Decorator/Component/SimpleCoffee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Decorator.Component 6 | { 7 | public class SimpleCoffee : ICoffee 8 | { 9 | public double GetCost() 10 | { 11 | return 1; 12 | } 13 | 14 | public string GetIngredients() 15 | { 16 | return "Coffee"; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Decorator/Decorator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Decorator/Decorator/CoffeeDecorator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Decorator.Component; 5 | 6 | namespace Decorator.Decorator 7 | { 8 | public abstract class CoffeeDecorator : ICoffee 9 | { 10 | private readonly ICoffee _decoratedCoffee; 11 | 12 | public CoffeeDecorator(ICoffee c) 13 | { 14 | this._decoratedCoffee = c; 15 | } 16 | 17 | public virtual double GetCost() 18 | { 19 | return _decoratedCoffee.GetCost(); 20 | } 21 | 22 | public virtual string GetIngredients() 23 | { 24 | return _decoratedCoffee.GetIngredients(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Decorator/Decorator/CoffeeWithMilk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Decorator.Component; 5 | 6 | namespace Decorator.Decorator 7 | { 8 | public class CoffeeWithMilk : CoffeeDecorator 9 | { 10 | public CoffeeWithMilk(ICoffee c) : base(c) { } 11 | 12 | public override double GetCost() 13 | { 14 | return base.GetCost() + 0.5; 15 | } 16 | 17 | public override string GetIngredients() 18 | { 19 | return base.GetIngredients() + ", Milk"; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Decorator/Decorator/CoffeeWithSprinkles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Decorator.Component; 5 | 6 | namespace Decorator.Decorator 7 | { 8 | class CoffeeWithSprinkles : CoffeeDecorator 9 | { 10 | public CoffeeWithSprinkles(ICoffee c) : base(c) { } 11 | 12 | public override double GetCost() 13 | { 14 | return base.GetCost() + 0.2; 15 | } 16 | 17 | public override string GetIngredients() 18 | { 19 | return base.GetIngredients() + ", Sprinkles"; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Decorator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Decorator.Component; 3 | using Decorator.Decorator; 4 | 5 | namespace Decorator 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | /* 12 | * More info: https://en.wikipedia.org/wiki/Decorator_pattern 13 | What problems can the Decorator design pattern solve? 14 | Responsibilities should be added to (and removed from) an object dynamically at run-time. 15 | A flexible alternative to subclassing for extending functionality should be provided. 16 | 17 | When using subclassing, different subclasses extend a class in different ways. 18 | But an extension is bound to the class at compile-time and can't be changed at run-time. 19 | */ 20 | 21 | void PrintInfo(ICoffee coffee) => Console.WriteLine("Cost: " + coffee.GetCost() + "; Ingredients: " + coffee.GetIngredients()); 22 | 23 | ICoffee c = new SimpleCoffee(); 24 | PrintInfo(c); 25 | 26 | c = new CoffeeWithMilk(c); 27 | PrintInfo(c); 28 | 29 | c = new CoffeeWithSprinkles(c); 30 | PrintInfo(c); 31 | 32 | 33 | 34 | var coffeeWithMilk = new CoffeeWithMilk(new SimpleCoffee()); 35 | PrintInfo(coffeeWithMilk); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Facade/CarFacade/CarFacade.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Facade.CarParts; 5 | 6 | namespace Facade.CarFacade 7 | { 8 | public class CarFacade 9 | { 10 | private readonly CarAccessories accessories; 11 | private readonly CarBody body; 12 | private readonly CarEngine engine; 13 | private readonly CarModel model; 14 | 15 | public CarFacade() 16 | { 17 | accessories = new CarAccessories(); 18 | body = new CarBody(); 19 | engine = new CarEngine(); 20 | model = new CarModel(); 21 | } 22 | 23 | public void CreateCompleteCar() 24 | { 25 | Console.WriteLine("******** Creating a Car **********"); 26 | model.SetModel(); 27 | engine.SetEngine(); 28 | body.SetBody(); 29 | accessories.SetAccessories(); 30 | 31 | Console.WriteLine("******** Car creation is completed. **********"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Facade/CarParts/CarAccessories.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Facade.CarParts 6 | { 7 | class CarAccessories 8 | { 9 | public void SetAccessories() 10 | { 11 | Console.WriteLine(" CarAccessories - SetAccessories"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Facade/CarParts/CarBody.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Facade.CarParts 6 | { 7 | class CarBody 8 | { 9 | public void SetBody() 10 | { 11 | Console.WriteLine(" CarBody - SetBody"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Facade/CarParts/CarEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Facade.CarParts 6 | { 7 | class CarEngine 8 | { 9 | public void SetEngine() 10 | { 11 | Console.WriteLine(" CarEngine - SetEngine"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Facade/CarParts/CarModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Facade.CarParts 6 | { 7 | class CarModel 8 | { 9 | public void SetModel() 10 | { 11 | Console.WriteLine(" CarModel - SetModel"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Facade/Facade.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Facade/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Facade 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | /* 10 | * More info: https://en.wikipedia.org/wiki/Facade_pattern 11 | What problems can the Facade design pattern solve? 12 | 13 | To make a complex subsystem easier to use, 14 | a simple interface should be provided for a set of interfaces in the subsystem. 15 | The dependencies on a subsystem should be minimized. 16 | 17 | Clients that access a complex subsystem directly refer to (depend on) many different objects 18 | having different interfaces (tight coupling), 19 | which makes the clients hard to implement, change, test, and reuse. 20 | */ 21 | 22 | var facade = new CarFacade.CarFacade(); 23 | 24 | facade.CreateCompleteCar(); 25 | 26 | Console.ReadKey(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Flyweight/Flyweight.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Flyweight/NormalImplementation/Clients/CoffeeMaker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.NormalImplementation.Clients 6 | { 7 | public class CoffeeMaker 8 | { 9 | private ReducedMemoryFootprintFlavorFactory _flavourFactory; 10 | 11 | public CoffeeMaker(ReducedMemoryFootprintFlavorFactory flavourFactory) 12 | { 13 | _flavourFactory = flavourFactory; 14 | } 15 | 16 | public void MakeCoffee(string flavour) 17 | { 18 | Console.WriteLine($"Making coffee with {_flavourFactory.GetFlavour(flavour).Flavour} flavor."); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Flyweight/NormalImplementation/CoffeeFlavour.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.NormalImplementation 6 | { 7 | public class CoffeeFlavour 8 | { 9 | private readonly string _flavour; 10 | 11 | public CoffeeFlavour(string flavour) 12 | { 13 | _flavour = flavour; 14 | } 15 | 16 | public string Flavour 17 | { 18 | get { return _flavour; } 19 | } 20 | 21 | public override bool Equals(object obj) 22 | { 23 | if (ReferenceEquals(null, obj)) return false; 24 | return obj is CoffeeFlavour && Equals((CoffeeFlavour)obj); 25 | } 26 | 27 | public bool Equals(CoffeeFlavour other) 28 | { 29 | return string.Equals(_flavour, other._flavour); 30 | } 31 | 32 | public override int GetHashCode() 33 | { 34 | return (_flavour != null ? _flavour.GetHashCode() : 0); 35 | } 36 | 37 | public static bool operator ==(CoffeeFlavour a, CoffeeFlavour b) 38 | { 39 | return Equals(a, b); 40 | } 41 | 42 | public static bool operator !=(CoffeeFlavour a, CoffeeFlavour b) 43 | { 44 | return !Equals(a, b); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Flyweight/NormalImplementation/ICoffeeFlavourFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.NormalImplementation 6 | { 7 | public interface ICoffeeFlavourFactory 8 | { 9 | CoffeeFlavour GetFlavour(string flavour); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Flyweight/NormalImplementation/Minimal/MinimumMemoryFootprint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Flyweight.NormalImplementation.Minimal 7 | { 8 | public class MinimumMemoryFootprint : ICoffeeFlavourFactory 9 | { 10 | private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); 11 | 12 | public CoffeeFlavour GetFlavour(string flavour) 13 | { 14 | return _cache.GetOrAdd(flavour, flv => new CoffeeFlavour(flv)); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Flyweight/NormalImplementation/ReducedMemoryFootprintFlavorFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace Flyweight.NormalImplementation 7 | { 8 | public class ReducedMemoryFootprintFlavorFactory : ICoffeeFlavourFactory 9 | { 10 | private readonly object _cacheLock = new object(); 11 | private readonly IDictionary _cache = new Dictionary(); 12 | 13 | public CoffeeFlavour GetFlavour(string flavour) 14 | { 15 | if (_cache.ContainsKey(flavour)) return _cache[flavour]; 16 | var coffeeFlavour = new CoffeeFlavour(flavour); 17 | ThreadPool.QueueUserWorkItem(AddFlavourToCache, coffeeFlavour); 18 | return coffeeFlavour; 19 | } 20 | 21 | private void AddFlavourToCache(object state) 22 | { 23 | var coffeeFlavour = (CoffeeFlavour)state; 24 | if (!_cache.ContainsKey(coffeeFlavour.Flavour)) 25 | { 26 | lock (_cacheLock) 27 | { 28 | if (!_cache.ContainsKey(coffeeFlavour.Flavour)) _cache.Add(coffeeFlavour.Flavour, coffeeFlavour); 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Flyweight/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Flyweight.NormalImplementation; 3 | using Flyweight.NormalImplementation.Clients; 4 | using Flyweight.NormalImplementation.Minimal; 5 | using Flyweight.SimpleImplementation; 6 | 7 | namespace Flyweight 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | 14 | /* 15 | * More info: https://en.wikipedia.org/wiki/Flyweight_pattern 16 | What problems can the Flyweight design pattern solve? [2] 17 | Large numbers of objects should be supported efficiently. 18 | Creating large numbers of objects should be avoided. 19 | 20 | When representing large text documents, for example, creating an object for each character in the document 21 | would result in a huge amount of objects that couldn't be processed efficiently. 22 | */ 23 | 24 | var simpleClient = new ClientObject(); 25 | //it'll share the same static FlyWeightPointer 26 | Console.WriteLine(simpleClient.Company); 27 | 28 | 29 | var flyWeightPointer = new ReducedMemoryFootprintFlavorFactory(); 30 | var minimalflyWeightPointer = new MinimumMemoryFootprint(); 31 | var coffeeMaker1 = new CoffeeMaker(flyWeightPointer); 32 | var coffeeMaker2 = new CoffeeMaker(flyWeightPointer); 33 | var coffeeMaker3 = new CoffeeMaker(flyWeightPointer); 34 | var coffeeMaker4 = new CoffeeMaker(flyWeightPointer); 35 | coffeeMaker1.MakeCoffee("Pepper?!"); 36 | coffeeMaker2.MakeCoffee("Lemon?"); 37 | coffeeMaker3.MakeCoffee("Chocolate"); 38 | coffeeMaker4.MakeCoffee("Spider"); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Flyweight/SimpleImplementation/ClientObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.SimpleImplementation 6 | { 7 | public class ClientObject 8 | { 9 | //Here the FlyweightPointer creates a static member Company, which is used for every object of ClientObject. 10 | public string Name { get; set; } 11 | public string Company 12 | { 13 | get 14 | { 15 | return FlyWeightPointer.Company.CompanyName; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Flyweight/SimpleImplementation/FlyWeight.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.SimpleImplementation 6 | { 7 | public class FlyWeight 8 | { 9 | public string CompanyName { get; set; } 10 | public string CompanyLocation { get; set; } 11 | public string CompanyWebSite { get; set; } 12 | //Bulky Data 13 | public byte[] CompanyLogo { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Flyweight/SimpleImplementation/FlyWeightPointer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Flyweight.SimpleImplementation 6 | { 7 | public static class FlyWeightPointer 8 | { 9 | public static readonly FlyWeight Company = new FlyWeight 10 | { 11 | CompanyName = "Abc", 12 | CompanyLocation = "XYZ", 13 | CompanyWebSite = "www.abc.com" 14 | // Load CompanyLogo here 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Interpreter/Context/TokenReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Interpreter.Expression; 4 | 5 | namespace Interpreter.Context 6 | { 7 | public class TokenReader 8 | { 9 | //"+ - 10 2 3" 10 | public IExpression ReadToken(List tokenList) 11 | { 12 | return ReadNextToken(tokenList); 13 | } 14 | 15 | private IExpression ReadNextToken(List tokenList) 16 | { 17 | if (int.TryParse(tokenList.First(), out var i)) //if the token is integer (terminal) 18 | { 19 | tokenList.RemoveAt(0); //process terminal expression 20 | return new NumberExpression(i); 21 | } 22 | 23 | return ReadNonTerminal(tokenList); //process nonTerminal expression 24 | } 25 | 26 | private IExpression ReadNonTerminal(List tokenList) 27 | { 28 | string token = tokenList.First(); 29 | tokenList.RemoveAt(0); //read the symbol 30 | 31 | IExpression left = ReadNextToken(tokenList); //read left expression 32 | IExpression right = ReadNextToken(tokenList); //read right expression 33 | 34 | if (token == "+") return new AddExpression(left, right); 35 | 36 | if (token == "-") return new SubtractExpression(left, right); 37 | 38 | return null; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Interpreter/Expression/AddExpression.cs: -------------------------------------------------------------------------------- 1 | namespace Interpreter.Expression 2 | { 3 | public class AddExpression : IExpression 4 | { 5 | readonly IExpression _leftExpression; 6 | readonly IExpression _rightExpression; 7 | 8 | public AddExpression(IExpression left, IExpression right) 9 | { 10 | _leftExpression = left; 11 | _rightExpression = right; 12 | } 13 | 14 | int IExpression.Interpret() 15 | { 16 | return _leftExpression.Interpret() + _rightExpression.Interpret(); 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return $"Add Expression {nameof(_leftExpression)}: {_leftExpression}, {nameof(_rightExpression)}: {_rightExpression}"; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Interpreter/Expression/IExpression.cs: -------------------------------------------------------------------------------- 1 | namespace Interpreter.Expression 2 | { 3 | public interface IExpression 4 | { 5 | int Interpret(); 6 | } 7 | } -------------------------------------------------------------------------------- /Interpreter/Expression/NumberExpression.cs: -------------------------------------------------------------------------------- 1 | namespace Interpreter.Expression 2 | { 3 | public class NumberExpression : IExpression 4 | { 5 | readonly int _number; 6 | 7 | public NumberExpression(int i) 8 | { 9 | _number = i; 10 | } 11 | 12 | int IExpression.Interpret() 13 | { 14 | return _number; 15 | } 16 | 17 | public override string ToString() 18 | { 19 | return $"Number Expression {nameof(_number)}: {_number}"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Interpreter/Expression/SubtractExpression.cs: -------------------------------------------------------------------------------- 1 | namespace Interpreter.Expression 2 | { 3 | public class SubtractExpression : IExpression 4 | { 5 | readonly IExpression _leftExpression; 6 | readonly IExpression _rightExpression; 7 | 8 | public SubtractExpression(IExpression left, IExpression right) 9 | { 10 | _leftExpression = left; 11 | _rightExpression = right; 12 | } 13 | 14 | int IExpression.Interpret() 15 | { 16 | return _leftExpression.Interpret() - _rightExpression.Interpret(); 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return $"Subtract Expression {nameof(_leftExpression)}: {_leftExpression}, {nameof(_rightExpression)}: {_rightExpression}"; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Interpreter/Interpreter.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Interpreter/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Interpreter.Context; 4 | using Interpreter.Expression; 5 | 6 | namespace Interpreter 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | /* 13 | * more info: https://sourcemaking.com/design_patterns/interpreter 14 | * https://www.codeproject.com/Articles/186183/Interpreter-Design-Pattern 15 | Intent 16 | Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. 17 | Map a domain to a language, the language to a grammar, and the grammar to a hierarchical object-oriented design. 18 | 19 | Problem 20 | A class of problems occurs repeatedly in a well-defined and well-understood domain. 21 | If the domain were characterized with a "language", 22 | then problems could be easily solved with an interpretation "engine". 23 | */ 24 | 25 | string tokenString = "+ - 10 2 3"; 26 | var tokenList = new List(tokenString.Split(' ')); 27 | IExpression expression = new TokenReader().ReadToken(tokenList); 28 | Console.WriteLine(expression.Interpret()); // (10 - 2) + 3 = 11 29 | 30 | 31 | tokenString = "- + 10 5 - 8 2"; 32 | tokenList = new List(tokenString.Split(' ')); 33 | expression = new TokenReader().ReadToken(tokenList); 34 | Console.WriteLine(expression.Interpret()); // (10 + 5) - (8 - 2) = 9 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Iterator/Aggregate/Aggregate.cs: -------------------------------------------------------------------------------- 1 | namespace Iterator.Aggregate 2 | { 3 | abstract class Aggregate 4 | { 5 | public abstract Iterator.Iterator CreateIterator(); 6 | } 7 | } -------------------------------------------------------------------------------- /Iterator/Aggregate/ConcreteAggregate.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using Iterator.Iterator; 3 | 4 | namespace Iterator.Aggregate 5 | { 6 | internal class ConcreteAggregate : Aggregate 7 | { 8 | private readonly ArrayList _items = new ArrayList(); 9 | 10 | public int Count => _items.Count; 11 | 12 | public object this[int index] 13 | { 14 | get => _items[index]; 15 | 16 | set => _items.Insert(index, value); 17 | } 18 | 19 | public override Iterator.Iterator CreateIterator() 20 | { 21 | return new ConcreteIterator(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Iterator/BuiltIn/MyCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Iterator.BuiltIn 7 | { 8 | public class MyCollection : IEnumerable 9 | { 10 | public T[] Items = new T[4]; 11 | public int CountIndex; 12 | 13 | public T this[int index] 14 | { 15 | get { return Items[index]; } 16 | set { Items[index] = value; } 17 | } 18 | 19 | public void Add(T item) 20 | { 21 | if(Items.Length == CountIndex) Array.Resize(ref Items, Items.Length * 2); 22 | 23 | Items[CountIndex++] = item; 24 | } 25 | 26 | public IEnumerator GetEnumerator() 27 | { 28 | return new MyCollectionEnumerator(this); 29 | 30 | /* 31 | //or simply: 32 | for (int i = 0; i < _countIndex; i++) yield return _items[i]; 33 | */ 34 | } 35 | 36 | IEnumerator IEnumerable.GetEnumerator() 37 | { 38 | return GetEnumerator(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Iterator/BuiltIn/MyCollectionEnumerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Iterator.BuiltIn 7 | { 8 | class MyCollectionEnumerator : IEnumerator 9 | { 10 | private int index = -1; 11 | private MyCollection _myCollection; 12 | 13 | public MyCollectionEnumerator(MyCollection myCollection) 14 | { 15 | _myCollection = myCollection; 16 | } 17 | 18 | public bool MoveNext() 19 | { 20 | return ++index < _myCollection.CountIndex; 21 | } 22 | 23 | public T Current 24 | { 25 | get 26 | { 27 | if (index < 0 || _myCollection.CountIndex <= index) return default(T); 28 | 29 | return _myCollection.Items[index]; 30 | } 31 | } 32 | 33 | object IEnumerator.Current => Current; 34 | 35 | 36 | 37 | 38 | 39 | 40 | public void Dispose() { } 41 | 42 | public void Reset() 43 | { 44 | throw new NotSupportedException(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Iterator/Iterator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Iterator/Iterator/ConcreteIterator.cs: -------------------------------------------------------------------------------- 1 | using Iterator.Aggregate; 2 | 3 | namespace Iterator.Iterator 4 | { 5 | internal class ConcreteIterator : Iterator 6 | { 7 | private readonly ConcreteAggregate _aggregate; 8 | 9 | private int _current; 10 | 11 | public ConcreteIterator(ConcreteAggregate aggregate) 12 | { 13 | _aggregate = aggregate; 14 | } 15 | 16 | public override object First() 17 | { 18 | return _aggregate[0]; 19 | } 20 | 21 | public override object Next() 22 | { 23 | return IsDone() ? null : _aggregate[++_current]; 24 | } 25 | 26 | public override object CurrentItem() 27 | { 28 | return _aggregate[_current]; 29 | } 30 | 31 | public override bool IsDone() 32 | { 33 | return _current >= _aggregate.Count - 1; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Iterator/Iterator/Iterator.cs: -------------------------------------------------------------------------------- 1 | namespace Iterator.Iterator 2 | { 3 | abstract class Iterator 4 | { 5 | public abstract object First(); 6 | public abstract object Next(); 7 | public abstract bool IsDone(); 8 | public abstract object CurrentItem(); 9 | } 10 | } -------------------------------------------------------------------------------- /Iterator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Iterator.Aggregate; 4 | using Iterator.BuiltIn; 5 | 6 | namespace Iterator 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | /* 13 | * More info: https://en.wikipedia.org/wiki/Iterator_pattern 14 | * http://www.dofactory.com/net/iterator-design-pattern 15 | What problems can the Iterator design pattern solve? 16 | The elements of an aggregate object should be accessed and traversed without exposing its representation (data structures). 17 | New traversal operations should be defined for an aggregate object without changing its interface. 18 | 19 | Defining access and traversal operations in the aggregate interface is inflexible 20 | because it commits the aggregate to particular access and traversal operations 21 | and makes it impossible to add new operations later without having to change the aggregate interface. 22 | */ 23 | 24 | var a = new ConcreteAggregate 25 | { 26 | [0] = "Item A", 27 | [1] = "Item B", 28 | [2] = "Item C", 29 | [3] = "Item D" 30 | }; 31 | 32 | Iterator.Iterator i = a.CreateIterator(); 33 | 34 | Console.WriteLine("Iterating over collection:"); 35 | 36 | object item = i.First(); 37 | 38 | while (item != null) 39 | { 40 | Console.WriteLine(item); 41 | item = i.Next(); 42 | } 43 | 44 | Console.WriteLine("========================== using the built in mechanisms or .Net=============================="); 45 | 46 | var myCollection = new MyCollection { 2, 3, 4, 5 }; 47 | 48 | myCollection.Add(25); 49 | myCollection.Add(34); 50 | myCollection.Add(32); 51 | 52 | foreach (var collectionItem in myCollection) 53 | { 54 | Console.WriteLine(collectionItem); 55 | } 56 | 57 | Console.WriteLine("==============================================================================================="); 58 | 59 | var enumerator = myCollection.GetEnumerator(); 60 | 61 | while (enumerator.MoveNext()) 62 | { 63 | Console.WriteLine(enumerator.Current); 64 | } 65 | 66 | Console.ReadKey(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hamid Mosalla 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mediator/Colleague/IUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Mediator.Mediator; 5 | 6 | namespace Mediator.Colleague 7 | { 8 | public interface IUser 9 | { 10 | void Send(string msg); 11 | void Receive(string msg); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Mediator/Colleague/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Mediator.Mediator; 5 | 6 | namespace Mediator.Colleague 7 | { 8 | public class User : IUser 9 | { 10 | private readonly IChatMediator _mediator; 11 | private readonly string _name; 12 | 13 | public User(IChatMediator med, string name) 14 | { 15 | this._mediator = med; 16 | this._name = name; 17 | } 18 | 19 | public void Send(string msg) 20 | { 21 | Console.WriteLine(this._name + ": Sending Message=" + msg); 22 | _mediator.SendMessage(msg, this); 23 | } 24 | 25 | public void Receive(string msg) 26 | { 27 | Console.WriteLine(this._name + ": Received Message:" + msg); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Mediator/Colleague/VipUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Mediator.Mediator; 5 | 6 | namespace Mediator.Colleague 7 | { 8 | public class VipUser : IUser 9 | { 10 | private readonly IChatMediator _mediator; 11 | private readonly string _name; 12 | 13 | public VipUser(IChatMediator med, string name) 14 | { 15 | this._mediator = med; 16 | this._name = name; 17 | } 18 | 19 | public void Send(string msg) 20 | { 21 | Console.WriteLine($"VIPuser {this._name} : Sending Message = {msg}"); 22 | _mediator.SendMessage(msg, this); 23 | } 24 | 25 | public void Receive(string msg) 26 | { 27 | Console.WriteLine($"VIPUser {this._name} : Received Message: {msg}"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Mediator/Mediator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Mediator/Mediator/ChatMediator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Mediator.Colleague; 6 | 7 | namespace Mediator.Mediator 8 | { 9 | public class ChatMediator : IChatMediator 10 | { 11 | private readonly List _users; 12 | 13 | public ChatMediator() 14 | { 15 | this._users = new List(); 16 | } 17 | 18 | public void AddUser(IUser user) 19 | { 20 | this._users.Add(user); 21 | } 22 | 23 | public void SendMessage(string msg, IUser incommingUser) 24 | { 25 | foreach (var user in _users.Where(user => user != incommingUser)) 26 | { 27 | user.Receive(msg); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Mediator/Mediator/IChatMediator.cs: -------------------------------------------------------------------------------- 1 | using Mediator.Colleague; 2 | 3 | namespace Mediator.Mediator 4 | { 5 | public interface IChatMediator 6 | { 7 | void SendMessage(string msg, IUser user); 8 | void AddUser(IUser user); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Mediator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Mediator.Colleague; 3 | using Mediator.Mediator; 4 | 5 | namespace Mediator 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | /* 12 | * More info: https://en.wikipedia.org/wiki/Mediator_pattern 13 | What problems can the Mediator design pattern solve? 14 | Tight coupling between a set of interacting objects should be avoided. 15 | It should be possible to change the interaction between a set of objects independently. 16 | 17 | Defining a set of interacting objects by accessing and updating each other directly is inflexible because it tightly couples the objects to each other and makes 18 | it impossible to change the interaction independently from (without having to change) the objects. 19 | 20 | And it stops the objects from being reusable and makes them hard to test. 21 | Tightly coupled objects are hard to implement, change, test, and reuse because they refer to and know about many different objects. 22 | */ 23 | 24 | IChatMediator mediator = new ChatMediator(); 25 | IUser user1 = new User(mediator, "Hamid"); 26 | IUser user2 = new User(mediator, "Lisa"); 27 | IUser user3 = new User(mediator, "Saurabh"); 28 | IUser user4 = new User(mediator, "David"); 29 | IUser vipUser = new VipUser(mediator, "Hans"); 30 | mediator.AddUser(user1); 31 | mediator.AddUser(user2); 32 | mediator.AddUser(user3); 33 | mediator.AddUser(user4); 34 | mediator.AddUser(vipUser); 35 | 36 | user1.Send("Hi All"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Memento/Memento.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Memento 6 | { 7 | public class Memento 8 | { 9 | public readonly Stack StringStates; 10 | 11 | public Memento() 12 | { 13 | this.StringStates = new Stack(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Memento/Memento.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Memento/OriginalObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Memento 6 | { 7 | public class OriginalObject 8 | { 9 | private readonly Memento _memento; 10 | 11 | public string FileState 12 | { 13 | get { return _memento.StringStates.Peek(); } 14 | set => _memento.StringStates.Push(value); 15 | } 16 | 17 | public OriginalObject(string str) 18 | { 19 | _memento = new Memento(); 20 | this._memento.StringStates.Push(str); 21 | } 22 | 23 | public void Revert() 24 | { 25 | _memento.StringStates.Pop(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Memento/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Memento 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | /* 10 | * More info: https://en.wikipedia.org/wiki/Memento_pattern 11 | What problems can the Memento design pattern solve? 12 | 13 | The internal state of an object should be saved externally so that the object can be restored to this state later. 14 | The object's encapsulation must not be violated. 15 | 16 | The problem is that a well designed object is encapsulated so that its representation (data structure) 17 | is hidden inside the object and can't be accessed from outside the object. 18 | */ 19 | 20 | var fileManager = new OriginalObject("State1"); 21 | fileManager.FileState = "State2"; 22 | fileManager.FileState = "State3"; 23 | fileManager.FileState = "State4"; 24 | 25 | Console.WriteLine($"First value {fileManager.FileState}"); 26 | fileManager.Revert(); 27 | Console.WriteLine($"After first revert {fileManager.FileState}"); 28 | fileManager.Revert(); 29 | Console.WriteLine($"After second revert {fileManager.FileState}"); 30 | 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NullObject/Animal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NullObject 6 | { 7 | abstract class Animal : IAnimal 8 | { 9 | public static readonly IAnimal Null = new NullAnimal(); 10 | 11 | private class NullAnimal : Animal 12 | { 13 | public override void MakeSound() { } 14 | } 15 | 16 | public abstract void MakeSound(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NullObject/Dog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NullObject 6 | { 7 | class Dog : IAnimal 8 | { 9 | public void MakeSound() 10 | { 11 | Console.WriteLine("Woof!"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NullObject/IAnimal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NullObject 6 | { 7 | interface IAnimal 8 | { 9 | void MakeSound(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NullObject/NullObject.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NullObject/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NullObject 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | /* 10 | * More info: https://en.wikipedia.org/wiki/Null_object_pattern 11 | * What problems can the Memento design pattern solve? 12 | In most object-oriented languages, such as Java or C#, references may be null. 13 | These references need to be checked to ensure they are not null before invoking any methods, 14 | because methods typically cannot be invoked on null references. 15 | 16 | The Objective-C language takes another approach to this problem and does nothing when sending a message to nil; 17 | if a return value is expected, nil (for objects), 0 (for numeric values), NO (for BOOL values), 18 | or a struct (for struct types) with all its members initialised 19 | to null/0/NO/zero-initialised struct is returned.[2] 20 | */ 21 | 22 | //Remember null object is an anti pattern: https://stackoverflow.com/questions/1178399/how-do-i-create-a-null-object-in-c-sharp 23 | IAnimal dog = new Dog(); 24 | dog.MakeSound(); 25 | 26 | // replace Animal.Null with null and you'll get an exception 27 | IAnimal unknown = Animal.Null; 28 | unknown.MakeSound(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Observer/BuiltInObserver/Observer/GermanyWeatherStation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Observer.BuiltInObserver.Subject; 3 | 4 | namespace Observer.BuiltInObserver.Observer 5 | { 6 | public class GermanyWeatherStation 7 | { 8 | public void GermanyWeatherChanged(object sender, WeatherEventArgs e) 9 | { 10 | Console.WriteLine($"Germany weather station receiving new transmission, temperature now is {e.Temperature + 4}"); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Observer/BuiltInObserver/Observer/IranWeatherStation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Observer.BuiltInObserver.Subject; 3 | 4 | namespace Observer.BuiltInObserver.Observer 5 | { 6 | public class IranWeatherStation 7 | { 8 | public void IranWeatherChanged(object sender, WeatherEventArgs e) 9 | { 10 | Console.WriteLine($"Iran weather station receiving new transmission, temperature now is {e.Temperature + 10}"); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Observer/BuiltInObserver/Observer/UnitedStateWeatherStation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Observer.BuiltInObserver.Subject; 3 | 4 | namespace Observer.BuiltInObserver.Observer 5 | { 6 | public class UnitedStateWeatherStation 7 | { 8 | public void UnitedStateWeatherChanged(object sender, WeatherEventArgs e) 9 | { 10 | Console.WriteLine($"US weather station receiving new transmission, temperature now is {e.Temperature + 2}"); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Observer/BuiltInObserver/Subject/WeatherEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Observer.BuiltInObserver.Subject 4 | { 5 | public class WeatherEventArgs : EventArgs 6 | { 7 | private double _temperature; 8 | 9 | public WeatherEventArgs(double temperature) 10 | { 11 | _temperature = temperature; 12 | } 13 | public double Temperature 14 | { 15 | get { return _temperature; } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Observer/BuiltInObserver/Subject/WeatherReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Observer.BuiltInObserver.Subject 4 | { 5 | public class WeatherReport 6 | { 7 | public event EventHandler WeatherChanged; 8 | 9 | public virtual void ReportWeather(WeatherEventArgs e) 10 | { 11 | // Make a temporary copy of the event to avoid possibility of 12 | // a race condition if the last subscriber unsubscribes 13 | // immediately after the null check and before the event is raised. 14 | EventHandler handler = WeatherChanged; 15 | 16 | if (handler != null) 17 | { 18 | Console.WriteLine($"Central weather station reporting, new weather is {e.Temperature} C"); 19 | handler(this, e); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Observer/Observer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Observer/ObserverObjects/ConcreteObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Observer.SubjectObjects; 3 | 4 | namespace Observer.ObserverObjects 5 | { 6 | internal class ConcreteObserver : Observer 7 | { 8 | private readonly string _name; 9 | 10 | private string _observerState; 11 | 12 | public ConcreteObserver(ConcreteSubject subject, string name) 13 | { 14 | Subject = subject; 15 | 16 | _name = name; 17 | } 18 | 19 | public ConcreteSubject Subject { get; set; } 20 | 21 | public override void Update() 22 | { 23 | _observerState = Subject.SubjectState; 24 | 25 | Console.WriteLine("Observer {0}'s new state is {1}", _name, _observerState); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Observer/ObserverObjects/Observer.cs: -------------------------------------------------------------------------------- 1 | namespace Observer.ObserverObjects 2 | { 3 | abstract class Observer 4 | { 5 | public abstract void Update(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Observer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Observer.BuiltInObserver; 3 | using Observer.BuiltInObserver.Observer; 4 | using Observer.BuiltInObserver.Subject; 5 | using Observer.ObserverObjects; 6 | using Observer.SubjectObjects; 7 | 8 | namespace Observer 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | /* 15 | * More info: https://en.wikipedia.org/wiki/Observer_pattern 16 | What problems can the Observer design pattern solve? 17 | 18 | A one-to-many dependency between objects should be defined without making the objects tightly coupled. 19 | It should be ensured that when one object changes state an open-ended number of dependent objects are updated automatically. 20 | It should be possible that one object can notify an open-ended number of other objects. 21 | 22 | Defining a one-to-many dependency between objects by defining one object (subject) 23 | that updates the state of dependent objects directly is inflexible because it commits (tightly couples) the subject to particular dependent objects. 24 | 25 | Tightly coupled objects are hard to implement, change, test, 26 | and reuse because they refer to and know about (how to update) many different objects with different interfaces. 27 | */ 28 | 29 | 30 | #region Observer pattern 31 | 32 | // Configure Observer pattern 33 | 34 | ConcreteSubject subject = new ConcreteSubject(); 35 | 36 | subject.Attach(new ConcreteObserver(subject, "X")); 37 | 38 | subject.Attach(new ConcreteObserver(subject, "Y")); 39 | 40 | subject.Attach(new ConcreteObserver(subject, "Z")); 41 | 42 | 43 | // Change subject and notify observers 44 | 45 | subject.SubjectState = "ABC"; 46 | 47 | subject.Notify(); 48 | 49 | #endregion 50 | 51 | #region .Net implementation of observer pattern 52 | 53 | var publisherWeatherStation = new WeatherReport(); 54 | 55 | var subscriberGermanyWeatherStation = new GermanyWeatherStation(); 56 | var subscriberIranWeatherStation = new IranWeatherStation(); 57 | var subscriberUnitedStateWeatherStation = new UnitedStateWeatherStation(); 58 | 59 | publisherWeatherStation.WeatherChanged += subscriberGermanyWeatherStation.GermanyWeatherChanged; 60 | publisherWeatherStation.WeatherChanged += subscriberIranWeatherStation.IranWeatherChanged; 61 | publisherWeatherStation.WeatherChanged += subscriberUnitedStateWeatherStation.UnitedStateWeatherChanged; 62 | 63 | publisherWeatherStation.ReportWeather(new WeatherEventArgs(temperature: 30)); 64 | 65 | #endregion 66 | 67 | Console.ReadKey(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Observer/SubjectObjects/ConcreteSubject.cs: -------------------------------------------------------------------------------- 1 | namespace Observer.SubjectObjects 2 | { 3 | class ConcreteSubject : Subject 4 | { 5 | private string _subjectState; 6 | 7 | public string SubjectState 8 | { 9 | get { return _subjectState; } 10 | 11 | set { _subjectState = value; } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Observer/SubjectObjects/Subject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Observer.SubjectObjects 4 | { 5 | internal abstract class Subject 6 | { 7 | private readonly List _observers = new List(); 8 | 9 | public void Attach(ObserverObjects.Observer observer) 10 | { 11 | _observers.Add(observer); 12 | } 13 | 14 | public void Detach(ObserverObjects.Observer observer) 15 | { 16 | _observers.Remove(observer); 17 | } 18 | 19 | public void Notify() 20 | { 21 | foreach (ObserverObjects.Observer o in _observers) o.Update(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Prototype/AbstractPrototype/IPerson.cs: -------------------------------------------------------------------------------- 1 | namespace Prototype.AbstractPrototype 2 | { 3 | interface IPerson 4 | { 5 | IPerson Clone(); 6 | } 7 | } -------------------------------------------------------------------------------- /Prototype/ConcretePrototype/Dick.cs: -------------------------------------------------------------------------------- 1 | using Prototype.AbstractPrototype; 2 | 3 | namespace Prototype.ConcretePrototype 4 | { 5 | class Dick : IPerson 6 | { 7 | private string _name = "Dick"; 8 | 9 | public IPerson Clone() 10 | { 11 | //shallow copy 12 | return (IPerson)this.MemberwiseClone(); 13 | 14 | //deep copy 15 | //return (IPerson)this.Clone(); 16 | } 17 | 18 | public override string ToString() 19 | { 20 | return _name; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Prototype/ConcretePrototype/Harry.cs: -------------------------------------------------------------------------------- 1 | using Prototype.AbstractPrototype; 2 | 3 | namespace Prototype.ConcretePrototype 4 | { 5 | class Harry : IPerson 6 | { 7 | private string _name = "Harry"; 8 | 9 | public IPerson Clone() 10 | { 11 | return (IPerson)this.MemberwiseClone(); 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return _name; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Prototype/ConcretePrototype/Tom.cs: -------------------------------------------------------------------------------- 1 | using Prototype.AbstractPrototype; 2 | 3 | namespace Prototype.ConcretePrototype 4 | { 5 | class Tom : IPerson 6 | { 7 | private string _name = "Tom"; 8 | 9 | public IPerson Clone() 10 | { 11 | return (IPerson)this.MemberwiseClone(); 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return _name; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Prototype/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Prototype.AbstractPrototype; 3 | using Prototype.PrototypeUsage; 4 | 5 | namespace Prototype 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | /* 13 | * More info: https://sourcemaking.com/design_patterns/prototype 14 | The Prototype design pattern solves problems like: 15 | 16 | Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. 17 | Co-opt one instance of a class for use as a breeder of all future instances. 18 | The new operator considered harmful. 19 | 20 | Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters. 21 | In this context, Prototype can avoid expensive "creation from scratch", and support cheap cloning of a pre-initialized prototype. 22 | 23 | More info: https://en.wikipedia.org/wiki/Prototype_pattern 24 | This pattern is used to: 25 | 26 | avoid subclasses of an object creator in the client application, like the factory method pattern does. 27 | avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) 28 | when it is prohibitively expensive for a given application. 29 | */ 30 | 31 | var people = new[] { "tom", "dick", "harry" }; 32 | 33 | foreach (var item in people) 34 | { 35 | IPerson prototype = Factory.GetPrototype(item); 36 | 37 | Console.WriteLine(item); 38 | } 39 | 40 | Console.WriteLine(Factory.GetPrototype("tom")); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Prototype/Prototype.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Prototype/PrototypeUsage/Factory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Prototype.AbstractPrototype; 4 | using Prototype.ConcretePrototype; 5 | 6 | namespace Prototype.PrototypeUsage 7 | { 8 | class Factory 9 | { 10 | private static readonly Dictionary Prototypes = new Dictionary(); 11 | 12 | static Factory() 13 | { 14 | Prototypes.Add("tom", new Tom()); 15 | Prototypes.Add("dick", new Dick()); 16 | Prototypes.Add("harry", new Harry()); 17 | } 18 | 19 | public static IPerson GetPrototype(string type) 20 | { 21 | try 22 | { 23 | return Prototypes.GetValueOrDefault(type).Clone(); 24 | } 25 | catch (NullReferenceException) 26 | { 27 | Console.WriteLine("Prototype with name: " + type + ", doesn't exist"); 28 | return null; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Proxy/ActualObjects/Car.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Proxy.ActualObjects 6 | { 7 | public class Car : ICar 8 | { 9 | public void DriveCar() 10 | { 11 | Console.WriteLine("Car has been driven!"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Proxy/ActualObjects/Driver.cs: -------------------------------------------------------------------------------- 1 | namespace Proxy.ActualObjects 2 | { 3 | public class Driver 4 | { 5 | public int Age { get; set; } 6 | 7 | public Driver(int age) 8 | { 9 | this.Age = age; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Proxy/ActualObjects/ICar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Proxy.ActualObjects 6 | { 7 | interface ICar 8 | { 9 | void DriveCar(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Proxy/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Proxy.ActualObjects; 3 | using Proxy.Proxy; 4 | 5 | namespace Proxy 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | /* 13 | * https://en.wikipedia.org/wiki/Proxy_pattern 14 | What problems can the Proxy design pattern solve? 15 | 1-The access to an object should be controlled. 16 | 2-Additional functionality should be provided when accessing an object. 17 | When accessing sensitive objects, for example, it should be possible to check that clients have the needed access rights. 18 | */ 19 | 20 | ICar car = new ProxyCar(new Driver(16)); 21 | car.DriveCar(); 22 | 23 | car = new ProxyCar(new Driver(25)); 24 | car.DriveCar(); 25 | 26 | Console.ReadKey(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Proxy/Proxy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Proxy/Proxy/ProxyCar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Proxy.ActualObjects; 5 | 6 | namespace Proxy.Proxy 7 | { 8 | public class ProxyCar : ICar 9 | { 10 | private Driver driver; 11 | private ICar realCar; 12 | 13 | public ProxyCar(Driver driver) 14 | { 15 | this.driver = driver; 16 | this.realCar = new Car(); 17 | } 18 | 19 | public void DriveCar() 20 | { 21 | if (driver.Age <= 16) 22 | Console.WriteLine("Sorry, the driver is too young to drive."); 23 | else 24 | this.realCar.DriveCar(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSharpDesignPatterns 2 | Design pattern samples in C# 3 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 5 | 6 | namespace RepositoryAndUnitOfWork.DomainModels 7 | { 8 | public class ApplicationUser : IdentityUser 9 | { 10 | public string UserFullName { get; set; } 11 | public string UserAddress { get; set; } 12 | public string UserPhoneNumber { get; set; } 13 | public string UserProfileEmail { get; set; } 14 | public string UserAvatar { get; set; } 15 | public string UserBio { get; set; } 16 | public string UserGender { get; set; } 17 | public string UserOccupation { get; set; } 18 | public string UserWebSite { get; set; } 19 | public string UserGoogleProfile { get; set; } 20 | public string UserFacebookProfile { get; set; } 21 | public string UserTwitterProfile { get; set; } 22 | public string UserLinkedInProfile { get; set; } 23 | public int? UserPoints { get; set; } 24 | public string UserSpeciality { get; set; } 25 | public string UserFavourites { get; set; } 26 | public DateTime UserRegisteredDate { get; set; } 27 | public DateTime? UserBanEndDate { get; set; } 28 | public DateTime? UserDateOfBirth { get; set; } 29 | public string UserHowFindUs { get; set; } 30 | 31 | 32 | public virtual ICollection
Articles { get; set; } 33 | public virtual ICollection ArticleRatings { get; set; } 34 | public virtual ICollection ArticleComments { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/Article.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RepositoryAndUnitOfWork.DomainModels 5 | { 6 | public class Article 7 | { 8 | public virtual ICollection ArticleArticleTags { get; set; } 9 | public virtual ICollection ArticleRatings { get; set; } 10 | public virtual ICollection ArticleComments { get; set; } 11 | 12 | public int ArticleId { get; set; } 13 | public string ArticleTitle { get; set; } 14 | public string ArticleSummary { get; set; } 15 | public DateTime ArticleDateCreated { get; set; } 16 | public DateTime? ArticleDateModified { get; set; } 17 | public string ArticleBody { get; set; } 18 | public Int64? ArticleViewCount { get; set; } 19 | 20 | public string ArticleStatus { get; set; } 21 | 22 | public bool IsOpenForComment { get; set; } 23 | 24 | 25 | //[ForeignKey("ArticleUserIDfk")] 26 | public virtual ApplicationUser ApplicationUser { get; set; } 27 | public string UserIDfk { get; set; } 28 | 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/ArticleArticleTag.cs: -------------------------------------------------------------------------------- 1 | namespace RepositoryAndUnitOfWork.DomainModels 2 | { 3 | public class ArticleArticleTag 4 | { 5 | public int ArticleId { get; set; } 6 | public int ArticleTagId { get; set; } 7 | public Article Article { get; set; } 8 | public ArticleTag ArticleTag { get; set; } 9 | 10 | 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/ArticleComment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RepositoryAndUnitOfWork.DomainModels 5 | { 6 | public class ArticleComment 7 | { 8 | public ArticleComment() 9 | { 10 | ArticleCommentChilds = new HashSet(); 11 | } 12 | 13 | public int ArticleCommentId { get; set; } 14 | public int? ArticleCommentParentId { get; set; } 15 | public ArticleComment ArticleCommentParent { get; set; } 16 | public virtual ICollection ArticleCommentChilds { get; set; } 17 | public DateTime ArticleCommentDateCreated { get; set; } 18 | public string ArticleCommentName { get; set; } 19 | public string ArticleCommentEmail { get; set; } 20 | public string ArticleCommentWebSite { get; set; } 21 | public string ArticleCommentGravatar { get; set; } 22 | public string ArticleCommentBody { get; set; } 23 | public bool IsCommentApproved { get; set; } 24 | 25 | //[ForeignKey("UserIDfk")] 26 | public virtual ApplicationUser ApplicationUser { get; set; } 27 | public string UserIDfk { get; set; } 28 | 29 | public int ArticleIDfk { get; set; } 30 | //[ForeignKey("ArticleIDfk")] 31 | public virtual Article Article { get; set; } 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/ArticleRating.cs: -------------------------------------------------------------------------------- 1 | namespace RepositoryAndUnitOfWork.DomainModels 2 | { 3 | public class ArticleRating 4 | { 5 | public int ArticleRatingId { get; set; } 6 | public double ArticleRatingScore { get; set; } 7 | 8 | //[ForeignKey("UserIDfk")] 9 | public virtual ApplicationUser ApplicationUser { get; set; } 10 | public string UserIDfk { get; set; } 11 | 12 | public int ArticleIDfk { get; set; } 13 | //[ForeignKey("ArticleIDfk")] 14 | public virtual Article Article { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/ArticleTag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RepositoryAndUnitOfWork.DomainModels 4 | { 5 | public class ArticleTag 6 | { 7 | public virtual ICollection ArticleArticleTags { get; set; } 8 | 9 | public int ArticleTagId { get; set; } 10 | public string ArticleTagName { get; set; } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/Contact.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RepositoryAndUnitOfWork.DomainModels 4 | { 5 | public class Contact 6 | { 7 | public int ContactId { get; set; } 8 | public DateTime ContactDate { get; set; } 9 | public string ContactName { get; set; } 10 | public string ContactEmail { get; set; } 11 | public string ContactBody { get; set; } 12 | public string ContactPhone { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/Portfolio.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RepositoryAndUnitOfWork.DomainModels 4 | { 5 | public class Portfolio 6 | { 7 | public int PortfolioId { get; set; } 8 | public string PortfolioTitle { get; set; } 9 | public DateTime PortfolioDateCreated { get; set; } 10 | public DateTime PortfolioDateBuilt { get; set; } 11 | public string PortfolioThumbnail { get; set; } 12 | public string PortfolioBody { get; set; } 13 | public string PortfolioSiteAddress { get; set; } 14 | public string PortfolioCategory { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/SiteOrder.cs: -------------------------------------------------------------------------------- 1 | namespace RepositoryAndUnitOfWork.DomainModels 2 | { 3 | public class SiteOrder 4 | { 5 | 6 | public int SiteOrderId { get; set; } 7 | 8 | 9 | //preliminary info - step1 10 | public string SiteOrderWebSiteType { get; set; } 11 | public string SiteOrderNumberOfMockUp { get; set; } 12 | public string SiteOrderDevelopmentComplexity { get; set; } 13 | public int? SiteOrderStaticPageNumber { get; set; } 14 | public bool SiteOrderDoesHaveDatabase { get; set; } 15 | public bool SiteOrderDoesHaveShoppingCart { get; set; } 16 | public bool SiteOrderDoesHaveShoppingCartWithoutRegister { get; set; } 17 | public bool SiteOrderDoesHaveBlog { get; set; } 18 | public bool SiteOrderDoesContentOnUs { get; set; } 19 | public string SiteOrderSupportType { get; set; } 20 | 21 | 22 | //site design info - step2 23 | public bool SiteOrderDoesUseTemplates { get; set; } 24 | public bool SiteOrderDoesUseCustomDesign { get; set; } 25 | public bool SiteOrderIsResponsive { get; set; } 26 | public bool SiteOrderIsOptimizedForMobile { get; set; } 27 | public bool SiteOrderIsOptimizedForAccessibility { get; set; } 28 | public bool SiteOrderIsOptimizedForLightness { get; set; } 29 | public bool SiteOrderDoesWithOkWithJavascriptDisabled { get; set; } 30 | public bool SiteOrderDoesHaveSeo { get; set; } 31 | public string SiteOrderSeoType { get; set; } 32 | public bool SiteOrderDoesHaveSiteMap { get; set; } 33 | 34 | 35 | //structural info - step3 36 | public bool SiteOrderIsCrossPlatform { get; set; } 37 | public bool SiteOrderDoesIncludeUnitTest { get; set; } 38 | public bool SiteOrderIsAsync { get; set; } 39 | public bool SiteOrderDoesConformToSolidDesign { get; set; } 40 | public bool SiteOrderIsSinglePage { get; set; } 41 | public bool SiteOrderDoesUseAjax { get; set; } 42 | public string SiteOrderDoesUseAjaxType { get; set; } 43 | public bool SiteOrderDoesHaveSsl { get; set; } 44 | public bool SiteOrderDoesSourceCodeIncluded { get; set; } 45 | public bool SiteOrderDoesHaveDocumentation { get; set; } 46 | 47 | 48 | //site part info - step4 49 | public bool SiteOrderDoesHaveRegistration { get; set; } 50 | public bool SiteOrderDoesHaveExternalAuth { get; set; } 51 | public bool SiteOrderDoesIncludeUserArea { get; set; } 52 | public bool SiteOrderDoesHaveUserProfile { get; set; } 53 | public bool SiteOrderDoesHaveAdminSection { get; set; } 54 | public bool SiteOrderDoesAdminManageUsers { get; set; } 55 | public bool SiteOrderDoesHaveFileManager { get; set; } 56 | public bool SiteOrderDoesHaveImageGallery { get; set; } 57 | public bool SiteOrderDoesHaveAdvancedHtmlEditor { get; set; } 58 | public bool SiteOrderDoesHaveSlideShow { get; set; } 59 | 60 | 61 | //auxiliary feature info - step5 62 | public bool SiteOrderDoesSupportTagging { get; set; } 63 | public bool SiteOrderDoesSupportCategory { get; set; } 64 | public bool SiteOrderDoesHaveCommenting { get; set; } 65 | public bool SiteOrderDoesHaveRatinging { get; set; } 66 | public bool SiteOrderDoesHaveNewsLetter { get; set; } 67 | public bool SiteOrderDoesHaveFeed { get; set; } 68 | public bool SiteOrderDoesVideoPlaying { get; set; } 69 | public bool SiteOrderDoesHaveForum { get; set; } 70 | public bool SiteOrderDoesHaveSearch { get; set; } 71 | public string SiteOrderSearchType { get; set; } 72 | 73 | 74 | //misc feature info - step6 75 | public bool SiteOrderDoesUseGoogleMap { get; set; } 76 | public bool SiteOrderDoesUseGoogleAnalytics { get; set; } 77 | public bool SiteOrderDoesUseSocialMedia { get; set; } 78 | public bool SiteOrderDoesIncludeChart { get; set; } 79 | public bool SiteOrderDoesIncludeDynamicChart { get; set; } 80 | public bool SiteOrderDoesIncludeAdvancedReport { get; set; } 81 | public bool SiteOrderDoesIncludeDomainAndHosting { get; set; } 82 | public bool SiteOrderDoesSupportIncluded { get; set; } 83 | public bool SiteOrderDoesHaveFaq { get; set; } 84 | public bool SiteOrderDoesHaveComplexFooter { get; set; } 85 | 86 | 87 | //check out info - step7 88 | public string SiteOrderFullName { get; set; } 89 | public string SiteOrderEmail { get; set; } 90 | public string SiteOrderPhone { get; set; } 91 | public string SiteOrderDesc { get; set; } 92 | public string SiteOrderTimeToDeliverMonth { get; set; } 93 | public string SiteOrderExample { get; set; } 94 | public string SiteOrderHowFindUs { get; set; } 95 | 96 | 97 | //final price info 98 | public decimal? SiteOrderFinalPrice { get; set; } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/DomainModels/SlideShow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RepositoryAndUnitOfWork.DomainModels 4 | { 5 | public class SlideShow 6 | { 7 | public int SlideShowId { get; set; } 8 | public DateTime SlideShowDateCreated { get; set; } 9 | public int? SlideShowPriority { get; set; } 10 | public string SlideShowTitle { get; set; } 11 | public string SlideShowBody { get; set; } 12 | public string SlideShowPictrure { get; set; } 13 | public string SlideShowLink { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/ORM/FreelancerBlogContext.cs: -------------------------------------------------------------------------------- 1 |  2 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore; 4 | using RepositoryAndUnitOfWork.DomainModels; 5 | 6 | namespace RepositoryAndUnitOfWork.ORM 7 | { 8 | public class FreelancerBlogContext : IdentityDbContext 9 | { 10 | public DbSet
Articles { get; set; } 11 | public DbSet ArticleComments { get; set; } 12 | public DbSet ArticleRatings { get; set; } 13 | public DbSet ArticleTags { get; set; } 14 | public DbSet ArticleArticleTags { get; set; } 15 | public DbSet Contacts { get; set; } 16 | public DbSet Portfolios { get; set; } 17 | public DbSet SiteOrders { get; set; } 18 | public DbSet SlideShows { get; set; } 19 | 20 | public FreelancerBlogContext(){ } 21 | 22 | public FreelancerBlogContext(DbContextOptions options) : base(options) { } 23 | } 24 | } -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RepositoryAndUnitOfWork.ORM; 3 | using RepositoryAndUnitOfWork.UnitOfWorkParts; 4 | 5 | namespace RepositoryAndUnitOfWork 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | /* 12 | What problems can the repository design pattern solve? 13 | In many applications, the business logic accesses data from data stores such as databases, 14 | SharePoint lists, or Web services. 15 | Directly accessing the data can result in the following: 16 | 17 | Duplicated code 18 | A higher potential for programming errors 19 | Weak typing of the business data 20 | Difficulty in centralizing data-related policies such as caching 21 | An inability to easily test the business logic in isolation from external dependencies 22 | 23 | More info: https://msdn.microsoft.com/en-us/library/ff649690.aspx 24 | */ 25 | 26 | //usually it's injected into dependent classes within the scope of a request. 27 | var db = new FreelancerBlogContext(); 28 | 29 | var unitOfWork = new UnitOfWork(db); 30 | 31 | var allArticleTags = unitOfWork.ArticleRepository.GetAllArticleTags(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/ArticleRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Microsoft.EntityFrameworkCore; 5 | using RepositoryAndUnitOfWork.DomainModels; 6 | using RepositoryAndUnitOfWork.ORM; 7 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 8 | 9 | namespace RepositoryAndUnitOfWork.Repositories 10 | { 11 | public class ArticleRepository : IArticleRepository 12 | { 13 | private FreelancerBlogContext _context; 14 | 15 | public ArticleRepository(FreelancerBlogContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | #region Article Aggregate Root 21 | public void Add(Article entity) 22 | { 23 | _context.Articles.Add(entity); 24 | } 25 | 26 | public void Remove(Article entity) 27 | { 28 | _context.Articles.Remove(entity); 29 | } 30 | 31 | public void Update(Article entity) 32 | { 33 | _context.Articles.Attach(entity); 34 | _context.Entry(entity).State = EntityState.Modified; 35 | } 36 | 37 | public Task
FindByIdAsync(int id) 38 | { 39 | return 40 | _context.Articles.Include(a => a.ApplicationUser) 41 | .Include(a => a.ArticleRatings) 42 | .Include(a => a.ArticleComments) 43 | .SingleOrDefaultAsync(a => a.ArticleId == id); 44 | } 45 | 46 | public Task> GetAllAsync() 47 | { 48 | return 49 | _context.Articles.Include(a => a.ApplicationUser) 50 | .Include(a => a.ArticleRatings) 51 | .Include(a => a.ArticleComments) 52 | .ToListAsync(); 53 | } 54 | 55 | 56 | 57 | public Task DeleteArticleAsync(Article article) 58 | { 59 | _context.Articles.Remove(article); 60 | return _context.SaveChangesAsync(); 61 | } 62 | 63 | public Task UpdateArticleAsync(Article article) 64 | { 65 | _context.Articles.Attach(article); 66 | 67 | var entity = _context.Entry(article); 68 | entity.State = EntityState.Modified; 69 | 70 | entity.Property(e => e.ArticleDateCreated).IsModified = false; 71 | entity.Property(e => e.ArticleId).IsModified = false; 72 | entity.Property(e => e.ArticleViewCount).IsModified = false; 73 | entity.Property(e => e.UserIDfk).IsModified = false; 74 | 75 | return _context.SaveChangesAsync(); 76 | } 77 | 78 | public Task> GetCurrentArticleTagsAsync(int articleId) 79 | { 80 | return 81 | _context.ArticleArticleTags.Where(a => a.ArticleId == articleId) 82 | .Join(_context.ArticleTags.ToList(), aat => aat.ArticleTagId, at => at.ArticleTagId, (aat, at) => at) 83 | .ToListAsync(); 84 | } 85 | 86 | public async Task IncreaseArticleViewCount(int articleId) 87 | { 88 | var article = await _context.Articles.SingleAsync(a => a.ArticleId == articleId); 89 | 90 | article.ArticleViewCount += 1; 91 | 92 | return await _context.SaveChangesAsync(); 93 | } 94 | 95 | public Task> GetArticlesByTag(int tagId) 96 | { 97 | return 98 | _context.ArticleArticleTags.Where(a => a.ArticleTagId.Equals(tagId)) 99 | .Join( 100 | _context.Articles.Include(a => a.ApplicationUser) 101 | .Include(a => a.ArticleComments) 102 | .Include(a => a.ArticleRatings), left => left.ArticleId, right => right.ArticleId, 103 | (aat, a) => a) 104 | .ToListAsync(); 105 | } 106 | 107 | public Task> GetLatestArticles(int numberOfArticles) 108 | { 109 | return _context.Articles.OrderByDescending(a => a.ArticleDateCreated).Take(numberOfArticles).ToListAsync(); 110 | } 111 | #endregion 112 | 113 | #region ArticleArticleTag 114 | public void AddArticleArticleTag(ArticleArticleTag entity) 115 | { 116 | _context.ArticleArticleTags.Add(entity); 117 | } 118 | 119 | public Task> GetAllArticleArticleTagAsync() 120 | { 121 | return _context.ArticleArticleTags.ToListAsync(); 122 | } 123 | 124 | public void AddRangeOfArticleArticleTag(List joinTableArtTagList) 125 | { 126 | _context.ArticleArticleTags.AddRange(joinTableArtTagList); 127 | } 128 | #endregion 129 | 130 | #region ArticleTag 131 | public void AddArticleTag(ArticleTag entity) 132 | { 133 | _context.ArticleTags.Add(entity); 134 | } 135 | 136 | public void RemoveArticleTag(ArticleTag entity) 137 | { 138 | _context.ArticleTags.Remove(entity); 139 | } 140 | 141 | public void UpdateArticleTag(ArticleTag entity) 142 | { 143 | _context.ArticleTags.Attach(entity); 144 | _context.Entry(entity).State = EntityState.Modified; 145 | } 146 | 147 | public Task FindArticleTagByIdAsync(int id) 148 | { 149 | return _context.ArticleTags.SingleOrDefaultAsync(a => a.ArticleTagId.Equals(id)); 150 | } 151 | 152 | public IEnumerable GetAllArticleTags() 153 | { 154 | return _context.ArticleTags.ToList(); 155 | } 156 | 157 | public Task> GetAllArticleTagsAsync() 158 | { 159 | return _context.ArticleTags.ToListAsync(); 160 | } 161 | 162 | public Task GetAllTagNamesArrayAsync() 163 | { 164 | return _context.ArticleTags.Select(a => a.ArticleTagName).ToArrayAsync(); 165 | } 166 | 167 | public Task AddRangeOfTags(IEnumerable exceptAddedTags) 168 | { 169 | var listOfAllTags = _context.ArticleTags.ToList(); 170 | 171 | foreach (var item in exceptAddedTags) 172 | { 173 | if (listOfAllTags.All(a => a.ArticleTagName != item)) 174 | { 175 | _context.ArticleTags.Add(new ArticleTag { ArticleTagName = item }); 176 | } 177 | } 178 | 179 | return _context.SaveChangesAsync(); 180 | } 181 | 182 | public async Task GetTagsByArticleIdAsync(int articleId) 183 | { 184 | var listOfArticleTags = await _context.ArticleArticleTags.Where(a => a.ArticleId == articleId).ToListAsync(); 185 | 186 | var arrayOfTags = 187 | listOfArticleTags.Join( 188 | await _context.ArticleTags.ToListAsync(), a => a.ArticleTagId, t => t.ArticleTagId, 189 | (a, t) => t.ArticleTagName).ToArray(); 190 | 191 | return string.Join(",", arrayOfTags); 192 | } 193 | 194 | public Task> FindByTagsName(IEnumerable delimitedTags) 195 | { 196 | return _context.ArticleTags.Join(delimitedTags, a => a.ArticleTagName, e => e, (a, e) => a).ToListAsync(); 197 | } 198 | 199 | public Task RemoveRangeOfArticleTags(List tagsToRemove) 200 | { 201 | _context.ArticleTags.RemoveRange(tagsToRemove); 202 | return _context.SaveChangesAsync(); 203 | } 204 | 205 | public Task RemoveTagRangeFromArticle(List tagsToRemove, int articleId) 206 | { 207 | var listOfaATags = 208 | _context.ArticleArticleTags.Join(tagsToRemove, a => a.ArticleTagId, t => t.ArticleTagId, (a, t) => a) 209 | .Where(c => c.ArticleId == articleId) 210 | .ToList(); 211 | 212 | _context.ArticleArticleTags.RemoveRange(listOfaATags); 213 | 214 | return _context.SaveChangesAsync(); 215 | } 216 | 217 | public Task AddTagRangeToArticle(List tagsToAdd, Article article) 218 | { 219 | foreach (var item in tagsToAdd) 220 | { 221 | _context.ArticleArticleTags.Add(new ArticleArticleTag {Article = article, ArticleTag = item}); 222 | } 223 | 224 | return _context.SaveChangesAsync(); 225 | } 226 | 227 | public Task DeleteArticleTagAsync(ArticleTag model) 228 | { 229 | _context.ArticleTags.Remove(model); 230 | 231 | return _context.SaveChangesAsync(); 232 | } 233 | 234 | public Task EditArticleTagAsync(ArticleTag model, string newTagName) 235 | { 236 | model.ArticleTagName = newTagName; 237 | return _context.SaveChangesAsync(); 238 | } 239 | #endregion 240 | 241 | #region ArticleRatingRepository 242 | public Task AddRatingForArticle(int id, double rating, string userIDfk) 243 | { 244 | var articleRating = new ArticleRating { ArticleIDfk = id, ArticleRatingScore = rating, UserIDfk = userIDfk }; 245 | 246 | _context.ArticleRatings.Add(articleRating); 247 | 248 | return _context.SaveChangesAsync(); 249 | } 250 | 251 | public bool IsRatedBefore(int id, string userIDfk) 252 | { 253 | var ratings = _context.ArticleRatings.Where(a => a.ArticleIDfk == id).ToList(); 254 | 255 | if (ratings.Count != 0) 256 | { 257 | bool eligibility = ratings.Any(r => r.UserIDfk == userIDfk); 258 | 259 | if (eligibility) 260 | { 261 | return true; 262 | } 263 | 264 | return false; 265 | } 266 | 267 | return false; 268 | } 269 | 270 | public Task UpdateArticleRating(int id, double rating, string userIDfk) 271 | { 272 | var articleRating = _context.ArticleRatings.Single(a => a.ArticleIDfk == id && a.UserIDfk == userIDfk); 273 | 274 | articleRating.ArticleRatingScore = rating; 275 | 276 | return _context.SaveChangesAsync(); 277 | } 278 | #endregion 279 | 280 | #region ArticleComment 281 | public Task FindCommentByIdAsync(int id) 282 | { 283 | return _context.ArticleComments.SingleOrDefaultAsync(a => a.ArticleCommentId.Equals(id)); 284 | } 285 | 286 | public Task> GetAllCommentAsync() 287 | { 288 | return 289 | _context.ArticleComments.OrderBy(a => a.IsCommentApproved) 290 | .ThenByDescending(a => a.ArticleCommentDateCreated) 291 | .Include(a => a.Article) 292 | .Include(a => a.ApplicationUser) 293 | .ToListAsync(); 294 | } 295 | 296 | public Task AddCommentToArticle(ArticleComment articleComment) 297 | { 298 | _context.ArticleComments.Add(articleComment); 299 | 300 | return _context.SaveChangesAsync(); 301 | } 302 | 303 | public Task DeleteArticleCommentAsync(ArticleComment model) 304 | { 305 | _context.ArticleComments.Remove(model); 306 | return _context.SaveChangesAsync(); 307 | } 308 | 309 | public Task ToggleArticleCommentApproval(ArticleComment model) 310 | { 311 | model.IsCommentApproved = !model.IsCommentApproved; 312 | 313 | return _context.SaveChangesAsync(); 314 | } 315 | 316 | public Task EditArticleCommentAsync(ArticleComment model, string newCommentBody) 317 | { 318 | model.ArticleCommentBody = newCommentBody; 319 | return _context.SaveChangesAsync(); 320 | } 321 | #endregion 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/ContactRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Microsoft.EntityFrameworkCore; 4 | using RepositoryAndUnitOfWork.DomainModels; 5 | using RepositoryAndUnitOfWork.ORM; 6 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 7 | 8 | namespace RepositoryAndUnitOfWork.Repositories 9 | { 10 | public class ContactRepository:IContactRepository 11 | { 12 | private FreelancerBlogContext _context; 13 | 14 | public ContactRepository(FreelancerBlogContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | 20 | public void Add(Contact entity) 21 | { 22 | _context.Contacts.Add(entity); 23 | } 24 | 25 | public void Remove(Contact entity) 26 | { 27 | _context.Contacts.Remove(entity); 28 | } 29 | 30 | public void Update(Contact entity) 31 | { 32 | _context.Contacts.Attach(entity); 33 | _context.Entry(entity).State = EntityState.Modified; 34 | } 35 | 36 | public Task FindByIdAsync(int id) 37 | { 38 | return _context.Contacts.SingleOrDefaultAsync(c => c.ContactId.Equals(id)); 39 | } 40 | 41 | public Task> GetAllAsync() 42 | { 43 | return _context.Contacts.ToListAsync(); 44 | } 45 | 46 | public Task AddNewContactAsync(Contact contact) 47 | { 48 | _context.Contacts.Add(contact); 49 | return _context.SaveChangesAsync(); 50 | } 51 | 52 | public Task DeleteContactAsync(Contact model) 53 | { 54 | _context.Contacts.Remove(model); 55 | return _context.SaveChangesAsync(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/PortfolioRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Microsoft.EntityFrameworkCore; 5 | using RepositoryAndUnitOfWork.DomainModels; 6 | using RepositoryAndUnitOfWork.ORM; 7 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 8 | 9 | namespace RepositoryAndUnitOfWork.Repositories 10 | { 11 | public class PortfolioRepository : IPortfolioRepository 12 | { 13 | private FreelancerBlogContext _context; 14 | 15 | public PortfolioRepository(FreelancerBlogContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | 21 | public void Add(Portfolio entity) 22 | { 23 | _context.Portfolios.Add(entity); 24 | } 25 | 26 | public void Remove(Portfolio entity) 27 | { 28 | _context.Portfolios.Remove(entity); 29 | } 30 | 31 | public void Update(Portfolio entity) 32 | { 33 | _context.Portfolios.Attach(entity); 34 | _context.Entry(entity).State = EntityState.Modified; 35 | } 36 | 37 | public Task FindByIdAsync(int id) 38 | { 39 | return _context.Portfolios.SingleOrDefaultAsync(p=>p.PortfolioId.Equals(id)); 40 | } 41 | 42 | public Task> GetAllAsync() 43 | { 44 | return _context.Portfolios.OrderByDescending(p=>p.PortfolioDateCreated).ToListAsync(); 45 | } 46 | 47 | public Task AddNewPortfolio(Portfolio portfolio) 48 | { 49 | _context.Portfolios.Add(portfolio); 50 | return _context.SaveChangesAsync(); 51 | } 52 | 53 | public Task DeletePortfolioAsync(Portfolio model) 54 | { 55 | _context.Portfolios.Remove(model); 56 | return _context.SaveChangesAsync(); 57 | } 58 | 59 | public void Detach(Portfolio model) 60 | { 61 | _context.Entry(model).State = EntityState.Detached; 62 | } 63 | 64 | public Task UpdatePortfolioAsync(Portfolio portfolio) 65 | { 66 | _context.Portfolios.Attach(portfolio); 67 | 68 | var entity = _context.Entry(portfolio); 69 | entity.State = EntityState.Modified; 70 | 71 | entity.Property(e => e.PortfolioDateCreated).IsModified = false; 72 | entity.Property(e => e.PortfolioThumbnail).IsModified = portfolio.PortfolioThumbnail != null; 73 | 74 | return _context.SaveChangesAsync(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/SiteOrderRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Microsoft.EntityFrameworkCore; 4 | using RepositoryAndUnitOfWork.DomainModels; 5 | using RepositoryAndUnitOfWork.ORM; 6 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 7 | 8 | namespace RepositoryAndUnitOfWork.Repositories 9 | { 10 | public class SiteOrderRepository : ISiteOrderRepository 11 | { 12 | private FreelancerBlogContext _context; 13 | 14 | public SiteOrderRepository(FreelancerBlogContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | public void Add(SiteOrder entity) 20 | { 21 | _context.SiteOrders.Add(entity); 22 | } 23 | 24 | public void Remove(SiteOrder entity) 25 | { 26 | _context.SiteOrders.Remove(entity); 27 | } 28 | 29 | public void Update(SiteOrder entity) 30 | { 31 | _context.SiteOrders.Attach(entity); 32 | _context.Entry(entity).State = EntityState.Modified; 33 | } 34 | 35 | public Task FindByIdAsync(int id) 36 | { 37 | return _context.SiteOrders.SingleAsync(s => s.SiteOrderId.Equals(id)); 38 | } 39 | 40 | public Task> GetAllAsync() 41 | { 42 | return _context.SiteOrders.ToListAsync(); 43 | } 44 | 45 | public Task AddSiteOrderAsync(SiteOrder siteOrder) 46 | { 47 | _context.SiteOrders.Add(siteOrder); 48 | 49 | return _context.SaveChangesAsync(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/SlideShowRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Microsoft.EntityFrameworkCore; 5 | using RepositoryAndUnitOfWork.DomainModels; 6 | using RepositoryAndUnitOfWork.ORM; 7 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 8 | 9 | namespace RepositoryAndUnitOfWork.Repositories 10 | { 11 | public class SlideShowRepository : ISlideShowRepository 12 | { 13 | private FreelancerBlogContext _context; 14 | 15 | public SlideShowRepository(FreelancerBlogContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | public void Add(SlideShow entity) 21 | { 22 | _context.SlideShows.Add(entity); 23 | } 24 | 25 | public void Remove(SlideShow entity) 26 | { 27 | _context.SlideShows.Remove(entity); 28 | } 29 | 30 | public void Update(SlideShow entity) 31 | { 32 | _context.SlideShows.Attach(entity); 33 | 34 | _context.Entry(entity).State = EntityState.Modified; 35 | } 36 | 37 | public Task FindByIdAsync(int id) 38 | { 39 | return _context.SlideShows.SingleOrDefaultAsync(s => s.SlideShowId.Equals(id)); 40 | } 41 | 42 | public Task> GetAllAsync() 43 | { 44 | return _context.SlideShows.OrderByDescending(s => s.SlideShowDateCreated).ToListAsync(); 45 | } 46 | 47 | public Task AddNewSlideShow(SlideShow slideShow) 48 | { 49 | _context.SlideShows.Add(slideShow); 50 | 51 | return _context.SaveChangesAsync(); 52 | } 53 | 54 | public Task DeleteSlideShowAsync(SlideShow model) 55 | { 56 | _context.SlideShows.Remove(model); 57 | 58 | return _context.SaveChangesAsync(); 59 | } 60 | 61 | public Task> GetAllAsyncForHomePage() 62 | { 63 | return 64 | _context.SlideShows.OrderBy(s => s.SlideShowPriority) 65 | .ThenByDescending(s => s.SlideShowDateCreated) 66 | .Take(10) 67 | .ToListAsync(); 68 | } 69 | 70 | public Task UpdateSlideShowAsync(SlideShow slideshow) 71 | { 72 | _context.SlideShows.Attach(slideshow); 73 | 74 | var entity = _context.Entry(slideshow); 75 | entity.State = EntityState.Modified; 76 | 77 | entity.Property(e => e.SlideShowDateCreated).IsModified = false; 78 | entity.Property(e => e.SlideShowPictrure).IsModified = slideshow.SlideShowPictrure != null; 79 | 80 | return _context.SaveChangesAsync(); 81 | } 82 | 83 | public void Detach(SlideShow model) 84 | { 85 | _context.Entry(model).State = EntityState.Detached; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/Repositories/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Microsoft.EntityFrameworkCore; 4 | using RepositoryAndUnitOfWork.DomainModels; 5 | using RepositoryAndUnitOfWork.ORM; 6 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 7 | 8 | namespace RepositoryAndUnitOfWork.Repositories 9 | { 10 | public class UserRepository : IUserRepository 11 | { 12 | private FreelancerBlogContext _context; 13 | 14 | public UserRepository(FreelancerBlogContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | 20 | public void Add(ApplicationUser entity) 21 | { 22 | _context.Users.Add(entity); 23 | } 24 | 25 | public void Remove(ApplicationUser entity) 26 | { 27 | _context.Users.Remove(entity); 28 | } 29 | 30 | public void Update(ApplicationUser user) 31 | { 32 | _context.Users.Attach(user); 33 | _context.Entry(user).State = EntityState.Modified; 34 | } 35 | 36 | public Task FindByIdAsync(string id) 37 | { 38 | return _context.Users.SingleAsync(u => u.Id.Equals(id)); 39 | 40 | //var userStore = new UserStore(_context); 41 | //var userManager = new UserManager(userStore); 42 | //var user = userManager.FindById(User.Identity.GetUserId()); 43 | } 44 | 45 | public Task> GetAllAsync() 46 | { 47 | return _context.Users.ToListAsync(); 48 | } 49 | 50 | public async Task UpdateUserProfileAsync(ApplicationUser user) 51 | { 52 | var model = await _context.Users.SingleAsync(u => u.Id.Equals(user.Id)); 53 | 54 | model.UserAddress = user.UserAddress; 55 | model.UserProfileEmail = user.UserProfileEmail; 56 | model.UserPhoneNumber = user.UserPhoneNumber; 57 | model.UserAvatar = user.UserAvatar ?? model.UserAvatar; 58 | model.UserBio = user.UserBio; 59 | model.UserDateOfBirth = user.UserDateOfBirth; 60 | model.UserFacebookProfile = user.UserFacebookProfile; 61 | model.UserFavourites = user.UserFavourites; 62 | model.UserFullName = user.UserFullName; 63 | model.UserGender = user.UserGender; 64 | model.UserGoogleProfile = user.UserGoogleProfile; 65 | model.UserHowFindUs = user.UserHowFindUs; 66 | model.UserLinkedInProfile = user.UserLinkedInProfile; 67 | model.UserOccupation = user.UserOccupation; 68 | model.UserSpeciality = user.UserSpeciality; 69 | model.UserTwitterProfile = user.UserTwitterProfile; 70 | model.UserWebSite = user.UserWebSite; 71 | 72 | 73 | return await _context.SaveChangesAsync(); 74 | } 75 | 76 | public void Detach(ApplicationUser model) 77 | { 78 | _context.Entry(model).State = EntityState.Detached; 79 | } 80 | 81 | public Task FindByUserNameAsync(string userName) 82 | { 83 | return 84 | _context.Users.Include(u => u.Articles) 85 | .ThenInclude(u => u.ArticleRatings) 86 | .Include(u => u.ArticleComments) 87 | .SingleOrDefaultAsync(u => u.Email.Equals(userName)); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryAndUnitOfWork.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | All 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/IArticleRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RepositoryAndUnitOfWork.DomainModels; 4 | 5 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 6 | { 7 | public interface IArticleRepository : IRepository 8 | { 9 | #region Article Aggregate Root 10 | Task UpdateArticleAsync(Article article); 11 | 12 | Task DeleteArticleAsync(Article article); 13 | Task> GetCurrentArticleTagsAsync(int articleId); 14 | 15 | Task IncreaseArticleViewCount(int articleId); 16 | 17 | Task> GetArticlesByTag(int tagId); 18 | Task> GetLatestArticles(int numberOfArticles); 19 | #endregion 20 | 21 | #region ArticleArticleTag 22 | void AddArticleArticleTag(ArticleArticleTag entity); 23 | 24 | Task> GetAllArticleArticleTagAsync(); 25 | 26 | void AddRangeOfArticleArticleTag(List joinTableArtTagList); 27 | #endregion 28 | 29 | #region ArticleTag 30 | 31 | void AddArticleTag(ArticleTag entity); 32 | 33 | void RemoveArticleTag(ArticleTag entity); 34 | 35 | void UpdateArticleTag(ArticleTag entity); 36 | 37 | Task FindArticleTagByIdAsync(int id); 38 | 39 | IEnumerable GetAllArticleTags(); 40 | 41 | Task> GetAllArticleTagsAsync(); 42 | Task GetAllTagNamesArrayAsync(); 43 | 44 | Task AddRangeOfTags(IEnumerable exceptAddedTags); 45 | 46 | Task GetTagsByArticleIdAsync(int articleId); 47 | 48 | Task> FindByTagsName(IEnumerable delimitedTags); 49 | 50 | Task RemoveRangeOfArticleTags(List tagsToRemove); 51 | 52 | Task RemoveTagRangeFromArticle(List tagsToRemove, int articleId); 53 | 54 | Task AddTagRangeToArticle(List tagsToAdd, Article article); 55 | Task DeleteArticleTagAsync(ArticleTag model); 56 | Task EditArticleTagAsync(ArticleTag model, string newTagName); 57 | #endregion 58 | 59 | #region ArticleRating 60 | Task AddRatingForArticle(int id, double rating, string userIDfk); 61 | 62 | bool IsRatedBefore(int id, string userIDfk); 63 | 64 | Task UpdateArticleRating(int id, double rating, string userIDfk); 65 | #endregion 66 | 67 | #region ArticleComment 68 | Task FindCommentByIdAsync(int id); 69 | Task> GetAllCommentAsync(); 70 | Task AddCommentToArticle(ArticleComment articleComment); 71 | Task DeleteArticleCommentAsync(ArticleComment model); 72 | Task ToggleArticleCommentApproval(ArticleComment model); 73 | Task EditArticleCommentAsync(ArticleComment model, string newCommentBody); 74 | #endregion 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/IContactRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RepositoryAndUnitOfWork.DomainModels; 3 | 4 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 5 | { 6 | public interface IContactRepository : IRepository 7 | { 8 | Task AddNewContactAsync(Contact contact); 9 | Task DeleteContactAsync(Contact model); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/IPortfolioRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RepositoryAndUnitOfWork.DomainModels; 3 | 4 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 5 | { 6 | public interface IPortfolioRepository : IRepository 7 | { 8 | Task AddNewPortfolio(Portfolio portfolio); 9 | Task DeletePortfolioAsync(Portfolio model); 10 | void Detach(Portfolio model); 11 | Task UpdatePortfolioAsync(Portfolio portfolio); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 5 | { 6 | public interface IRepository where T : class 7 | { 8 | void Add(T entity); 9 | void Remove(T entity); 10 | void Update(T entity); 11 | Task FindByIdAsync(TKey id); 12 | Task > GetAllAsync(); 13 | 14 | // redundant, redundant, Unit Of Work will handle it 15 | //void Save(); 16 | 17 | // too generic, hard to implement for other providers 18 | //IQueryable Find(Expression> predicate); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/ISiteOrderRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RepositoryAndUnitOfWork.DomainModels; 3 | 4 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 5 | { 6 | public interface ISiteOrderRepository : IRepository 7 | { 8 | Task AddSiteOrderAsync(SiteOrder siteOrder); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/ISlideShowRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RepositoryAndUnitOfWork.DomainModels; 4 | 5 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 6 | { 7 | public interface ISlideShowRepository : IRepository 8 | { 9 | Task AddNewSlideShow(SlideShow slideShow); 10 | Task DeleteSlideShowAsync(SlideShow model); 11 | Task> GetAllAsyncForHomePage(); 12 | Task UpdateSlideShowAsync(SlideShow slideshow); 13 | void Detach(SlideShow model); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/RepositoryInterfaces/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RepositoryAndUnitOfWork.DomainModels; 3 | 4 | namespace RepositoryAndUnitOfWork.RepositoryInterfaces 5 | { 6 | public interface IUserRepository : IRepository 7 | { 8 | Task UpdateUserProfileAsync(ApplicationUser user); 9 | void Detach(ApplicationUser model); 10 | Task FindByUserNameAsync(string userName); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/UnitOfWorkParts/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 4 | 5 | namespace RepositoryAndUnitOfWork.UnitOfWorkParts 6 | { 7 | public interface IUnitOfWork : IDisposable 8 | { 9 | IArticleRepository ArticleRepository { get; } 10 | IUserRepository UserRepository { get; } 11 | IContactRepository ContactRepository { get; } 12 | IPortfolioRepository PortfolioRepository { get; } 13 | ISiteOrderRepository SiteOrderRepository { get; } 14 | ISlideShowRepository SlideShowRepository { get; } 15 | int Save(); 16 | Task SaveAsync(); 17 | new void Dispose(); 18 | } 19 | } -------------------------------------------------------------------------------- /RepositoryAndUnitOfWork/UnitOfWorkParts/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RepositoryAndUnitOfWork.ORM; 4 | using RepositoryAndUnitOfWork.Repositories; 5 | using RepositoryAndUnitOfWork.RepositoryInterfaces; 6 | 7 | namespace RepositoryAndUnitOfWork.UnitOfWorkParts 8 | { 9 | public class UnitOfWork : IUnitOfWork 10 | { 11 | 12 | private readonly FreelancerBlogContext _context; 13 | 14 | public UnitOfWork(FreelancerBlogContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | private IArticleRepository _articleRepository; 20 | private IUserRepository _userRepository; 21 | private IContactRepository _contactRepository; 22 | private IPortfolioRepository _portfolioRepository; 23 | private ISiteOrderRepository _siteOrderRepository; 24 | private ISlideShowRepository _slideShowRepository; 25 | 26 | public IArticleRepository ArticleRepository 27 | { 28 | get 29 | { 30 | if (this._articleRepository == null) 31 | { 32 | this._articleRepository = new ArticleRepository(_context); 33 | } 34 | return _articleRepository; 35 | } 36 | } 37 | public IUserRepository UserRepository 38 | { 39 | get 40 | { 41 | if (this._userRepository == null) 42 | { 43 | this._userRepository = new UserRepository(_context); 44 | } 45 | return _userRepository; 46 | } 47 | } 48 | public IContactRepository ContactRepository 49 | { 50 | get 51 | { 52 | if (this._contactRepository == null) 53 | { 54 | this._contactRepository = new ContactRepository(_context); 55 | } 56 | return _contactRepository; 57 | } 58 | } 59 | public IPortfolioRepository PortfolioRepository 60 | { 61 | get 62 | { 63 | if (this._portfolioRepository == null) 64 | { 65 | this._portfolioRepository = new PortfolioRepository(_context); 66 | } 67 | return _portfolioRepository; 68 | } 69 | } 70 | public ISiteOrderRepository SiteOrderRepository 71 | { 72 | get 73 | { 74 | if (this._siteOrderRepository == null) 75 | { 76 | this._siteOrderRepository = new SiteOrderRepository(_context); 77 | } 78 | return _siteOrderRepository; 79 | } 80 | } 81 | public ISlideShowRepository SlideShowRepository 82 | { 83 | get 84 | { 85 | if (this._slideShowRepository == null) 86 | { 87 | this._slideShowRepository = new SlideShowRepository(_context); 88 | } 89 | return _slideShowRepository; 90 | } 91 | } 92 | 93 | public int Save() 94 | { 95 | return _context.SaveChanges(); 96 | } 97 | 98 | public Task SaveAsync() 99 | { 100 | return _context.SaveChangesAsync(); 101 | } 102 | 103 | private bool _disposed = false; 104 | 105 | protected virtual void Dispose(bool disposing) 106 | { 107 | if (!this._disposed) 108 | { 109 | if (disposing) 110 | { 111 | _context.Dispose(); 112 | } 113 | } 114 | this._disposed = true; 115 | } 116 | 117 | public void Dispose() 118 | { 119 | Dispose(true); 120 | GC.SuppressFinalize(this); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Singleton/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Singleton 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | /* 10 | More info: http://csharpindepth.com/Articles/General/Singleton.aspx 11 | */ 12 | 13 | Console.WriteLine("Hello World!"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Singleton/Singleton.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Singleton/SingletonLazy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Singleton 6 | { 7 | public sealed class SingletonLazy 8 | { 9 | private static readonly Lazy lazy = new Lazy(() => new SingletonLazy()); 10 | 11 | public static SingletonLazy Instance { get { return lazy.Value; } } 12 | 13 | private SingletonLazy() 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Singleton/SingletonWithLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Singleton 6 | { 7 | public sealed class SingletonWithLock 8 | { 9 | private static SingletonWithLock instance = null; 10 | private static readonly object padlock = new object(); 11 | 12 | SingletonWithLock() 13 | { 14 | } 15 | 16 | public static SingletonWithLock Instance 17 | { 18 | get 19 | { 20 | lock (padlock) 21 | { 22 | if (instance == null) 23 | { 24 | instance = new SingletonWithLock(); 25 | } 26 | return instance; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Singleton/SingletonWithoutLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Singleton 6 | { 7 | public sealed class SingletonWithoutLock 8 | { 9 | private static readonly SingletonWithoutLock instance = new SingletonWithoutLock(); 10 | 11 | // Explicit static constructor to tell C# compiler 12 | // not to mark type as beforefieldinit 13 | static SingletonWithoutLock() 14 | { 15 | } 16 | 17 | private SingletonWithoutLock() 18 | { 19 | } 20 | 21 | public static SingletonWithoutLock Instance 22 | { 23 | get 24 | { 25 | return instance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Specification/BaseSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | using Specification; 6 | 7 | namespace Specification 8 | { 9 | // https://github.com/dotnet-architecture/eShopOnWeb 10 | public abstract class BaseSpecification : ISpecification 11 | { 12 | public BaseSpecification(Expression> criteria) 13 | { 14 | Criteria = criteria; 15 | } 16 | public Expression> Criteria { get; } 17 | public List>> Includes { get; } = new List>>(); 18 | public List IncludeStrings { get; } = new List(); 19 | 20 | protected virtual void AddInclude(Expression> includeExpression) 21 | { 22 | Includes.Add(includeExpression); 23 | } 24 | // string-based includes allow for including children of children, e.g. Basket.Items.Product 25 | protected virtual void AddInclude(string includeString) 26 | { 27 | IncludeStrings.Add(includeString); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Specification/Basket.cs: -------------------------------------------------------------------------------- 1 | namespace Specification 2 | { 3 | public class Basket 4 | { 5 | public object Items { get; set; } 6 | public int Id { get; set; } 7 | public string BuyerId { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Specification/BasketWithItemsSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Specification 6 | { 7 | public class BasketWithItemsSpecification : BaseSpecification 8 | { 9 | public BasketWithItemsSpecification(int basketId) 10 | : base(b => b.Id == basketId) 11 | { 12 | AddInclude(b => b.Items); 13 | } 14 | public BasketWithItemsSpecification(string buyerId) 15 | : base(b => b.BuyerId == buyerId) 16 | { 17 | AddInclude(b => b.Items); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Specification/ISpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | 6 | namespace Specification 7 | { 8 | // https://github.com/dotnet-architecture/eShopOnWeb 9 | public interface ISpecification 10 | { 11 | Expression> Criteria { get; } 12 | List>> Includes { get; } 13 | List IncludeStrings { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Specification/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Specification 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine("Hello World!"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Specification/Repository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Specification 6 | { 7 | public class Repository 8 | { 9 | //public IEnumerable List(ISpecification spec) 10 | //{ 11 | // // fetch a Queryable that includes all expression-based includes 12 | // var queryableResultWithIncludes = spec.Includes 13 | // .Aggregate(_dbContext.Set().AsQueryable(), 14 | // (current, include) => current.Include(include)); 15 | 16 | // // modify the IQueryable to include any string-based include statements 17 | // var secondaryResult = spec.IncludeStrings 18 | // .Aggregate(queryableResultWithIncludes, 19 | // (current, include) => current.Include(include)); 20 | 21 | // // return the result of the query using the specification's criteria expression 22 | // return secondaryResult 23 | // .Where(spec.Criteria) 24 | // .AsEnumerable(); 25 | //} 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Specification/Specification.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.2 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /State/Legacy/GumballMachine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace State.Legacy 4 | { 5 | public class GumballMachine 6 | { 7 | private int _count; 8 | private State _state = State.NoQuarters; 9 | 10 | public GumballMachine(int count) 11 | { 12 | _count = count; 13 | } 14 | 15 | public void InsertQuarter() 16 | { 17 | switch (_state) 18 | { 19 | case State.NoQuarters: 20 | _state = State.HasQuarters; 21 | Console.WriteLine("Inserted a quarter"); 22 | break; 23 | case State.Sold: 24 | Console.WriteLine("Please wait for current gumball to come out"); 25 | break; 26 | case State.HasQuarters: 27 | Console.WriteLine("Can't add more quarters"); 28 | break; 29 | case State.NoGumballs: 30 | Console.WriteLine("Out of Stock"); 31 | break; 32 | default: 33 | throw new ArgumentOutOfRangeException(); 34 | } 35 | } 36 | 37 | public void EjectQuarter() 38 | { 39 | switch (_state) 40 | { 41 | case State.NoQuarters: 42 | Console.WriteLine("Nothing to eject"); 43 | break; 44 | case State.Sold: 45 | Console.WriteLine("Sorry, you have already turned the crank"); 46 | break; 47 | case State.HasQuarters: 48 | Console.WriteLine("Ejecting.."); 49 | _state = State.NoQuarters; 50 | break; 51 | case State.NoGumballs: 52 | Console.WriteLine("Can't eject, never accepted quarters"); 53 | break; 54 | default: 55 | throw new ArgumentOutOfRangeException(); 56 | } 57 | } 58 | 59 | public void TurnCrank() 60 | { 61 | switch (_state) 62 | { 63 | case State.NoQuarters: 64 | Console.WriteLine("Insert quarter First"); 65 | break; 66 | case State.Sold: 67 | Console.WriteLine("Turning twice won't get you a gumball"); 68 | break; 69 | case State.HasQuarters: 70 | Console.WriteLine("Getting gumball..."); 71 | _state = State.Sold; 72 | Dispense(); 73 | break; 74 | case State.NoGumballs: 75 | Console.WriteLine("Out of Stock"); 76 | break; 77 | default: 78 | throw new ArgumentOutOfRangeException(); 79 | } 80 | } 81 | 82 | private void Dispense() 83 | { 84 | switch (_state) 85 | { 86 | case State.NoQuarters: 87 | Console.WriteLine("You need to pay first"); 88 | break; 89 | case State.Sold: 90 | Console.WriteLine("A Gumball comes rolling out"); 91 | _count--; 92 | _state = _count == 0 ? _state = State.NoGumballs : State.NoQuarters; 93 | break; 94 | case State.HasQuarters: 95 | case State.NoGumballs: 96 | Console.WriteLine("Can't dispense"); 97 | break; 98 | default: 99 | throw new ArgumentOutOfRangeException(); 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /State/Legacy/State.cs: -------------------------------------------------------------------------------- 1 | namespace State.Legacy 2 | { 3 | public enum State 4 | { 5 | Sold, HasQuarters, NoQuarters, NoGumballs 6 | } 7 | } -------------------------------------------------------------------------------- /State/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.StateMachineContext; 3 | 4 | namespace State 5 | { 6 | static class Program 7 | { 8 | public static void Main() 9 | { 10 | /*https://stackoverflow.com/a/30424503/1650277 11 | What problems can the State design pattern solve? 12 | 13 | An object should change its behavior when its internal state changes. 14 | State-specific behavior should be defined independently. 15 | That is, new states should be added and the behavior of 16 | existing states should be changed independently. 17 | 18 | Implementing state-specific behavior directly within a class is inflexible because 19 | it commits the class to a particular behavior and makes it impossible to add a new state 20 | or change the behavior of an existing state later independently from (without changing) the class. 21 | * 22 | * Strategy pattern vs State pattern 23 | States store a reference to the context object that contains them. Strategies do not. 24 | States are allowed to replace themselves (IE: to change the state of the context object to something else), while Strategies are not. 25 | Strategies are passed to the context object as parameters, while States are created by the context object itself. 26 | Strategies only handle a single, specific task, while States provide the underlying implementation for everything (or most everything) the context object does. 27 | */ 28 | 29 | LegacyTest(); 30 | Console.WriteLine(); 31 | var gumballmachine = new GumballMachine(5); 32 | gumballmachine.InsertQuarter(); 33 | gumballmachine.TurnCrank(); 34 | gumballmachine.InsertQuarter(); 35 | gumballmachine.TurnCrank(); 36 | } 37 | 38 | private static void LegacyTest() 39 | { 40 | var machine = new Legacy.GumballMachine(2); 41 | machine.InsertQuarter(); 42 | machine.TurnCrank(); 43 | machine.InsertQuarter(); 44 | machine.EjectQuarter(); 45 | machine.InsertQuarter(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /State/Refactored/Abstraction/IState.cs: -------------------------------------------------------------------------------- 1 | namespace State.Refactored.Abstraction 2 | { 3 | public interface IState 4 | { 5 | void InsertQuarter(); 6 | void EjectQuarter(); 7 | void TurnCrank(); 8 | void Dispense(); 9 | } 10 | } -------------------------------------------------------------------------------- /State/Refactored/StateMachineContext/GumballMachine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | 4 | namespace State.Refactored.StateMachineContext 5 | { 6 | public class GumballMachine 7 | { 8 | public int Count { get; private set; } 9 | 10 | public IState SoldOutState; 11 | public IState NoQuarterState; 12 | public IState HasQuarterState; 13 | public IState SoldState; 14 | public IState WinnerState; 15 | 16 | public IState State { get; set; } 17 | 18 | public GumballMachine(int count) 19 | { 20 | Count = count; 21 | SoldOutState = new SoldOutState(this); 22 | NoQuarterState = new NoQuarterState(this); 23 | HasQuarterState = new HasQuarterState(this); 24 | SoldState = new SoldState(this); 25 | WinnerState = new WinnerState(this); 26 | if (Count > 0) 27 | { 28 | State = NoQuarterState; 29 | } 30 | } 31 | 32 | public void InsertQuarter() 33 | { 34 | State.InsertQuarter(); 35 | } 36 | 37 | public void EjectQuarter() 38 | { 39 | State.EjectQuarter(); 40 | } 41 | 42 | public void TurnCrank() 43 | { 44 | State.TurnCrank(); 45 | State.Dispense(); 46 | } 47 | 48 | public void ReleaseBall() 49 | { 50 | Console.WriteLine("A ball comes rolling down"); 51 | if (Count == 0) return; 52 | Count--; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /State/Refactored/VariousStates/HasQuarterState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | using State.Refactored.StateMachineContext; 4 | 5 | namespace State 6 | { 7 | public class HasQuarterState : IState 8 | { 9 | private GumballMachine Machine { get; } 10 | readonly Random _random = new Random(DateTime.Now.Millisecond); 11 | 12 | public HasQuarterState(GumballMachine gumballMachine) 13 | { 14 | Machine = gumballMachine; 15 | } 16 | 17 | public void InsertQuarter() 18 | { 19 | Console.WriteLine("Can't insert more than one"); 20 | } 21 | 22 | public void EjectQuarter() 23 | { 24 | Console.WriteLine("Quarter returned"); 25 | Machine.State = Machine.NoQuarterState; 26 | } 27 | 28 | public void TurnCrank() 29 | { 30 | Console.WriteLine("You turned the crank"); 31 | var winner = _random.Next(10); 32 | if ((winner == 5) && (Machine.Count > 1)) 33 | Machine.State = Machine.WinnerState; 34 | else 35 | { 36 | Machine.State = Machine.SoldState; 37 | } 38 | } 39 | 40 | public void Dispense() 41 | { 42 | Console.WriteLine("Can't do that"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /State/Refactored/VariousStates/NoQuarterState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | using State.Refactored.StateMachineContext; 4 | 5 | namespace State 6 | { 7 | public class NoQuarterState : IState 8 | { 9 | public GumballMachine Machine { get; } 10 | 11 | public NoQuarterState(GumballMachine machine) 12 | { 13 | Machine = machine; 14 | } 15 | public void InsertQuarter() 16 | { 17 | Console.WriteLine("Inserted a quarter"); 18 | Machine.State = Machine.HasQuarterState; 19 | } 20 | 21 | public void EjectQuarter() 22 | { 23 | Console.Write("Can't eject anything"); 24 | } 25 | 26 | public void TurnCrank() 27 | { 28 | Console.WriteLine("Can't turn crank without a quarter"); 29 | } 30 | 31 | public void Dispense() 32 | { 33 | Console.WriteLine("Can't dispense"); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /State/Refactored/VariousStates/SoldOutState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | using State.Refactored.StateMachineContext; 4 | 5 | namespace State 6 | { 7 | public class SoldOutState : IState 8 | { 9 | public GumballMachine Machine { get; } 10 | 11 | public SoldOutState(GumballMachine gumballMachine) 12 | { 13 | Machine = gumballMachine; 14 | } 15 | 16 | public void InsertQuarter() 17 | { 18 | Console.WriteLine("Sorry! Sold Out"); 19 | } 20 | 21 | public void EjectQuarter() 22 | { 23 | Console.WriteLine("Can't eject when sold out"); 24 | } 25 | 26 | public void TurnCrank() 27 | { 28 | Console.WriteLine("turning crank achieves nothing"); 29 | } 30 | 31 | public void Dispense() 32 | { 33 | Console.WriteLine("Can't dispense when out of stock"); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /State/Refactored/VariousStates/SoldState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | using State.Refactored.StateMachineContext; 4 | 5 | namespace State 6 | { 7 | public class SoldState : IState 8 | { 9 | private GumballMachine Machine { get; } 10 | 11 | public SoldState(GumballMachine gumballMachine) 12 | { 13 | Machine = gumballMachine; 14 | } 15 | 16 | public void InsertQuarter() 17 | { 18 | Console.WriteLine("Please wait, already in progress"); 19 | } 20 | 21 | public void EjectQuarter() 22 | { 23 | Console.WriteLine("Can't eject, already turned the crank"); 24 | } 25 | 26 | public void TurnCrank() 27 | { 28 | Console.WriteLine("Turning twice achieves nothing"); 29 | } 30 | 31 | public void Dispense() 32 | { 33 | Machine.ReleaseBall(); 34 | if (Machine.Count > 0) 35 | { 36 | Machine.State = Machine.NoQuarterState; 37 | } 38 | else 39 | { 40 | Console.WriteLine("Oops! No more gumballs"); 41 | Machine.State = Machine.SoldOutState; 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /State/Refactored/VariousStates/WinnerState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using State.Refactored.Abstraction; 3 | using State.Refactored.StateMachineContext; 4 | 5 | namespace State 6 | { 7 | public class WinnerState : IState 8 | { 9 | private GumballMachine Machine { get; } 10 | 11 | public WinnerState(GumballMachine gumballMachine) 12 | { 13 | Machine = gumballMachine; 14 | } 15 | 16 | public void InsertQuarter() 17 | { 18 | Console.WriteLine("Please wait, already in progress"); 19 | } 20 | 21 | public void EjectQuarter() 22 | { 23 | Console.WriteLine("Can't eject, already turned the crank"); 24 | } 25 | 26 | public void TurnCrank() 27 | { 28 | Console.WriteLine("Turning twice achieves nothing"); 29 | } 30 | 31 | 32 | public void Dispense() 33 | { 34 | Console.WriteLine("You Won!! 2 gumballs for the price of one"); 35 | Machine.ReleaseBall(); 36 | if (Machine.Count == 0) 37 | { 38 | Machine.State = Machine.SoldOutState; 39 | Console.WriteLine("Oops! No more gumballs"); 40 | } 41 | else 42 | { 43 | Machine.ReleaseBall(); 44 | Machine.State = Machine.NoQuarterState; 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /State/State.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Strategy/Anbstraction/IDataReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Strategy.Anbstraction 6 | { 7 | public interface IDataReader 8 | { 9 | void ReadData(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Strategy/Implementations/JsonDataReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Strategy.Anbstraction; 5 | 6 | namespace Strategy.Implementations 7 | { 8 | class JsonDataReader:IDataReader 9 | { 10 | public void ReadData() 11 | { 12 | Console.WriteLine("Reading data from json."); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Strategy/Implementations/SqlDataReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Strategy.Anbstraction; 5 | 6 | namespace Strategy.Implementations 7 | { 8 | class SqlDataReader:IDataReader 9 | { 10 | public void ReadData() 11 | { 12 | Console.WriteLine("Reading data from sql."); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Strategy/Implementations/XmlDataReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Strategy.Anbstraction; 5 | 6 | namespace Strategy.Implementations 7 | { 8 | class XmlDataReader: IDataReader 9 | { 10 | public void ReadData() 11 | { 12 | Console.WriteLine("Reading data from XML."); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Strategy/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Strategy.Anbstraction; 4 | using Strategy.Implementations; 5 | 6 | namespace Strategy 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | /* 13 | More info: https://en.wikipedia.org/wiki/Strategy_pattern 14 | http://www.dofactory.com/net/strategy-design-pattern 15 | 16 | What problems can the Strategy design pattern solve? [3] 17 | 18 | A class should be configured with an algorithm instead of implementing an algorithm directly. 19 | An algorithm should be selected and exchanged at run-time. 20 | 21 | What is an algorithm? An algorithm is usually defined as a procedure that takes some value as input, 22 | performs a finite number of steps, and produces some value as output. 23 | From a more general point of view, 24 | an algorithm is a piece of code that does something appropriate. 25 | 26 | Implementing an algorithm directly within the class that uses the algorithm is inflexible because 27 | it commits the class to a particular algorithm at compile-time and makes it impossible to change 28 | the algorithm later independently from (without having to change) the class. This also stops the class 29 | from being reusable when another algorithm should be used. 30 | 31 | */ 32 | 33 | var dataReaders = new List { new XmlDataReader(), new JsonDataReader(), new SqlDataReader() }; 34 | 35 | //Our client doesn't care how data readers reads data, it only cares that there is a method called *ReadData* which it can call. 36 | foreach (var dataReader in dataReaders) 37 | { 38 | dataReader.ReadData(); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Strategy/Strategy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TemplateMethod/AuditExample/Abstraction/IMessageAuditor.cs: -------------------------------------------------------------------------------- 1 | namespace TemplateMethod.AuditExample.Abstraction 2 | { 3 | public interface IMessageAuditor 4 | { 5 | void Audit(string messageType, string userName, string correlationId, string messageBody); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /TemplateMethod/AuditExample/Abstraction/MessageProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Principal; 2 | using System.Threading; 3 | 4 | namespace TemplateMethod.AuditExample.Abstraction 5 | { 6 | public abstract class MessageProcessor 7 | { 8 | private readonly IMessageAuditor _auditor; 9 | 10 | public MessageProcessor(IMessageAuditor auditor) 11 | { 12 | _auditor = auditor; 13 | } 14 | 15 | // Template Methods that must be overriden by subclasses 16 | 17 | protected abstract string messageType { get; } 18 | 19 | public void ProcessMessage(Message message) 20 | { 21 | var principal = Thread.CurrentPrincipal; 22 | 23 | if (authorize(message, principal)) 24 | { 25 | doWork(message); 26 | audit(message, principal); 27 | } 28 | } 29 | 30 | protected abstract bool authorize(Message message, IPrincipal principal); 31 | 32 | protected abstract void doWork(Message message); 33 | 34 | private void audit(Message message, IPrincipal principal) 35 | { 36 | _auditor.Audit(messageType, principal.Identity.Name, message.CorrelationId, message.Body.ToString()); 37 | } 38 | } 39 | 40 | public class Message 41 | { 42 | public string CorrelationId { get; set; } 43 | public object Body { get; set; } 44 | } 45 | } -------------------------------------------------------------------------------- /TemplateMethod/AuditExample/CancelOrderMessageProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Principal; 2 | using TemplateMethod.AuditExample.Abstraction; 3 | 4 | namespace TemplateMethod.AuditExample 5 | { 6 | public class CancelOrderMessageProcessor : MessageProcessor 7 | 8 | { 9 | public CancelOrderMessageProcessor(IMessageAuditor auditor) : base(auditor) { } 10 | 11 | protected override string messageType 12 | { 13 | get 14 | { 15 | return "CancelOrder"; 16 | } 17 | } 18 | 19 | protected override bool authorize(Message message, IPrincipal principal) 20 | { 21 | // go check whether the IPrincipal user is the same user who placed the order 22 | 23 | // referenced by the contents of the message 24 | 25 | return true; 26 | } 27 | 28 | protected override void doWork(Message message) 29 | { 30 | // find the order number and cancel the order in the backend system 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TemplateMethod/AuditExample/MoreInfo.txt: -------------------------------------------------------------------------------- 1 | http://codebetter.com/jeremymiller/2006/04/11/six-design-patterns-to-start-with/ 2 | 3 | So what have we really accomplished here? For one thing we’ve standardized the message processing. 4 | If we need to handle any new message types we can just create a new subclass and fill in the missing pieces. 5 | Somebody new to the project can create a new message type by following the established pattern. 6 | We’ve also eliminated some code duplication, and that’s always a good thing. -------------------------------------------------------------------------------- /TemplateMethod/DrinkExample/Abstraction/Beverage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TemplateMethod.DrinkExample.Abstraction 4 | { 5 | public abstract class Beverage 6 | { 7 | protected int _sugar; 8 | 9 | public void Prepare() 10 | { 11 | Boil(); 12 | Brew(); 13 | Pour(); 14 | if (WantsCondiments) 15 | AddCondiments(); 16 | 17 | } 18 | 19 | public bool WantsCondiments { private get; set; } 20 | 21 | private void Boil() 22 | { 23 | Console.WriteLine("Boling Water"); 24 | } 25 | 26 | protected abstract void Brew(); 27 | 28 | private void Pour() 29 | { 30 | Console.WriteLine("Pouring in Cup"); 31 | } 32 | 33 | protected abstract void AddCondiments(); 34 | 35 | public int AddSugar { get; set; } 36 | 37 | protected void Sugar() { } 38 | } 39 | } -------------------------------------------------------------------------------- /TemplateMethod/DrinkExample/Implementations/Coffee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using TemplateMethod.DrinkExample.Abstraction; 3 | 4 | namespace TemplateMethod.DrinkExample.Implementations 5 | { 6 | class Coffee : Beverage 7 | { 8 | protected override void Brew() 9 | { 10 | Console.WriteLine("Add Coffee Grounds to water and boil"); 11 | } 12 | 13 | protected override void AddCondiments() 14 | { 15 | Console.WriteLine("Add Milk and Sugar"); 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TemplateMethod/DrinkExample/Implementations/Tea.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using TemplateMethod.DrinkExample.Abstraction; 3 | 4 | namespace TemplateMethod.DrinkExample.Implementations 5 | { 6 | class Tea : Beverage 7 | { 8 | protected override void Brew() 9 | { 10 | Console.WriteLine("Adding tea leaves to water and boil"); 11 | } 12 | 13 | protected override void AddCondiments() 14 | { 15 | Console.WriteLine("Adding Lemon and Sugar"); 16 | Sugar(); 17 | } 18 | 19 | private new void Sugar() 20 | { 21 | Console.WriteLine($"adding {_sugar} spoons of sugar"); 22 | } 23 | 24 | public new int AddSugar 25 | { 26 | set { _sugar = value; } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /TemplateMethod/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using TemplateMethod.DrinkExample.Implementations; 3 | 4 | namespace TemplateMethod 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | /* 11 | * More info: https://en.wikipedia.org/wiki/Template_method_pattern 12 | Usage 13 | The template method is used in frameworks, where each implements the invariant parts of a domain's architecture, leaving "placeholders" for customization options. 14 | This is an example of inversion of control. The template method is used for the following reasons: 15 | 16 | Let subclasses implement varying behavior (through method overriding). 17 | 18 | Avoid duplication in the code: the general workflow structure is implemented once in the abstract class's algorithm, 19 | and necessary variations are implemented in the subclasses. 20 | 21 | Control at what point(s) subclassing is allowed. As opposed to a simple polymorphic override, 22 | where the base method would be entirely rewritten allowing radical change to the workflow, only the specific details of the workflow are allowed to change. 23 | */ 24 | 25 | var tea = new Tea(); 26 | 27 | tea.WantsCondiments = true; 28 | tea.AddSugar = 5; 29 | tea.Prepare(); 30 | 31 | Console.WriteLine("===================================================================="); 32 | 33 | var coffee = new Coffee(); 34 | 35 | coffee.WantsCondiments = true; 36 | coffee.Prepare(); 37 | 38 | Console.ReadKey(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TemplateMethod/TemplateMethod.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Visitor/Elements/BoldText.cs: -------------------------------------------------------------------------------- 1 | using Visitor.ObjectStructure; 2 | using Visitor.Visitors; 3 | 4 | namespace Visitor.Elements 5 | { 6 | public class BoldText : DocumentPart 7 | { 8 | public override void Accept(IVisitor visitor) 9 | { 10 | visitor.Visit(this); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Visitor/Elements/Hyperlink.cs: -------------------------------------------------------------------------------- 1 | using Visitor.ObjectStructure; 2 | using Visitor.Visitors; 3 | 4 | namespace Visitor.Elements 5 | { 6 | public class Hyperlink : DocumentPart 7 | { 8 | public string Url { get; set; } 9 | 10 | public override void Accept(IVisitor visitor) 11 | { 12 | visitor.Visit(this); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Visitor/Elements/PlainText.cs: -------------------------------------------------------------------------------- 1 | using Visitor.ObjectStructure; 2 | using Visitor.Visitors; 3 | 4 | namespace Visitor.Elements 5 | { 6 | public class PlainText : DocumentPart 7 | { 8 | public override void Accept(IVisitor visitor) 9 | { 10 | visitor.Visit(this); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Visitor/ObjectStructure/Document.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Visitor.Visitors; 3 | 4 | namespace Visitor.ObjectStructure 5 | { 6 | public class Document 7 | { 8 | private readonly List _mParts; 9 | 10 | public Document(params DocumentPart[] documents) 11 | { 12 | _mParts = new List(); 13 | _mParts.AddRange(documents); 14 | } 15 | 16 | public void Accept(IVisitor visitor) 17 | { 18 | foreach (DocumentPart part in this._mParts) part.Accept(visitor); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Visitor/ObjectStructure/DocumentPart.cs: -------------------------------------------------------------------------------- 1 | using Visitor.Visitors; 2 | 3 | namespace Visitor.ObjectStructure 4 | { 5 | public abstract class DocumentPart 6 | { 7 | public string Text { get; set; } 8 | public abstract void Accept(IVisitor visitor); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Visitor/OldImplementation/OldImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace OldImplementation 4 | { 5 | public abstract class DocumentPart 6 | { 7 | public string Text { get; private set; } 8 | public abstract string ToHTML(); 9 | public abstract string ToPlainText(); 10 | public abstract string ToLatex(); 11 | } 12 | 13 | public class PlainText : DocumentPart 14 | { 15 | public override string ToHTML() 16 | { 17 | return this.Text; 18 | } 19 | public override string ToPlainText() 20 | { 21 | return this.Text; 22 | } 23 | public override string ToLatex() 24 | { 25 | return this.Text; 26 | } 27 | } 28 | 29 | public class BoldText : DocumentPart 30 | { 31 | public override string ToHTML() 32 | { 33 | return "" + this.Text + ""; 34 | } 35 | public override string ToPlainText() 36 | { 37 | return "**" + this.Text + "**"; 38 | } 39 | public override string ToLatex() 40 | { 41 | return "\\textbf{" + this.Text + "}"; 42 | } 43 | } 44 | 45 | public class Hyperlink : DocumentPart 46 | { 47 | public string Url { get; private set; } 48 | 49 | public override string ToHTML() 50 | { 51 | return "" + this.Text + ""; 52 | } 53 | public override string ToPlainText() 54 | { 55 | return this.Text + " [" + this.Url + "]"; 56 | } 57 | public override string ToLatex() 58 | { 59 | return "\\href{" + this.Url + "}{" + this.Text + "}"; 60 | } 61 | } 62 | 63 | public class Document 64 | { 65 | private List m_parts; 66 | 67 | public string ToHTML() 68 | { 69 | string output = ""; 70 | foreach (DocumentPart part in this.m_parts) 71 | { 72 | output += part.ToHTML(); 73 | } 74 | return output; 75 | } 76 | 77 | public string ToPlainText() 78 | { 79 | string output = ""; 80 | foreach (DocumentPart part in this.m_parts) 81 | { 82 | output += part.ToPlainText(); 83 | } 84 | return output; 85 | } 86 | 87 | public string ToLatex() 88 | { 89 | string output = ""; 90 | foreach (DocumentPart part in this.m_parts) 91 | { 92 | output += part.ToLatex(); 93 | } 94 | return output; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Visitor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Visitor.Elements; 3 | using Visitor.ObjectStructure; 4 | using Visitor.Visitors; 5 | 6 | namespace Visitor 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | /* 13 | More info: https://manski.net/2013/05/the-visitor-pattern-explained 14 | What problems can the Visitor design pattern solve? 15 | 16 | It should be possible to define a new operation for (some) classe 17 | s of an object structure without changing the classes. 18 | 19 | When new operations are needed frequently and the object structure consists of many unrelated classes, 20 | it's inflexible to add new subclasses each time a new operation is required because "[..] distributing 21 | all these operations across the various node classes leads to a system that's hard to understand, maintain, and change." 22 | 23 | */ 24 | 25 | var doc = new Document(new PlainText { Text = "Plain" }, new Hyperlink { Text = "Hyper", Url = "Link" }); 26 | var visitor = new HtmlVisitor(); 27 | doc.Accept(visitor); 28 | Console.WriteLine($"Plain text plus Hyperlink {visitor.Output}"); 29 | 30 | var doc2 = new Document(new PlainText { Text = "Plain" }, new Hyperlink { Text = "Hyper", Url = "Link" }); 31 | var visitor2 = new LatexVisitor(); 32 | doc.Accept(visitor); 33 | Console.WriteLine($"Plain text plus Hyperlink {visitor.Output}"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Visitor/Visitor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Visitor/Visitors/HtmlVisitor.cs: -------------------------------------------------------------------------------- 1 | using Visitor.Elements; 2 | 3 | namespace Visitor.Visitors 4 | { 5 | public class HtmlVisitor : IVisitor 6 | { 7 | public string Output 8 | { 9 | get { return this.m_output; } 10 | set { this.m_output = value; } 11 | } 12 | 13 | private string m_output = ""; 14 | 15 | public void Visit(PlainText docPart) 16 | { 17 | this.m_output += docPart.Text; 18 | } 19 | 20 | public void Visit(BoldText docPart) 21 | { 22 | this.m_output += "" + docPart.Text + ""; 23 | } 24 | 25 | public void Visit(Hyperlink docPart) 26 | { 27 | this.m_output += "" + docPart.Text + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Visitor/Visitors/IVisitor.cs: -------------------------------------------------------------------------------- 1 | using Visitor.Elements; 2 | 3 | namespace Visitor.Visitors 4 | { 5 | public interface IVisitor 6 | { 7 | void Visit(PlainText docPart); 8 | void Visit(BoldText docPart); 9 | void Visit(Hyperlink docPart); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Visitor/Visitors/LatexVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Visitor.Elements; 5 | 6 | namespace Visitor.Visitors 7 | { 8 | public class LatexVisitor : IVisitor 9 | { 10 | public string Output 11 | { 12 | get { return this.m_output; } 13 | } 14 | private string m_output = ""; 15 | 16 | public void Visit(PlainText docPart) 17 | { 18 | this.m_output += docPart.Text; 19 | } 20 | 21 | public void Visit(BoldText docPart) 22 | { 23 | this.m_output += "\\textbf{" + docPart.Text + "}"; 24 | } 25 | 26 | public void Visit(Hyperlink docPart) 27 | { 28 | this.m_output += "\\href{" + docPart.Url + "}{" + docPart.Text + "}"; 29 | } 30 | } 31 | } 32 | --------------------------------------------------------------------------------