├── SLIDES-DependencyInjection.pdf ├── LooseCoupling ├── People.Service │ ├── appsettings.json │ ├── appsettings.Development.json │ ├── Models │ │ ├── IPeopleProvider.cs │ │ └── StaticPeopleProvider.cs │ ├── Program.cs │ ├── People.Service.csproj │ ├── Properties │ │ └── launchSettings.json │ ├── Controllers │ │ └── PeopleController.cs │ └── Startup.cs ├── LateBindingAssemblies │ ├── Newtonsoft.Json.dll │ ├── PersonRepository.CSV.dll │ ├── PersonRepository.Service.dll │ ├── PersonRepository.CSV.deps.json │ └── PersonRepository.Service.deps.json ├── PeopleViewer.Autofac │ ├── packages.config │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── MainWindow.xaml.cs │ ├── App.xaml.cs │ ├── MainWindow.xaml │ ├── Converters.cs │ └── PeopleViewer.Autofac.csproj ├── PeopleViewer │ ├── packages.config │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── MainWindow.xaml.cs │ ├── App.xaml.cs │ ├── MainWindow.xaml │ ├── Converters.cs │ └── PeopleViewer.csproj ├── Common │ ├── Common.csproj │ ├── IPersonRepository.cs │ └── Person.cs ├── PeopleViewer.Ninject │ ├── App.config │ ├── packages.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml.cs │ ├── MainWindow.xaml.cs │ ├── MainWindow.xaml │ ├── Converters.cs │ └── PeopleViewer.Ninject.csproj ├── PeopleViewer.Autofac.LateBinding │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── autofac.json │ ├── MainWindow.xaml.cs │ ├── App.xaml.cs │ ├── MainWindow.xaml │ ├── Converters.cs │ └── PeopleViewer.Autofac.LateBinding.csproj ├── PersonRepository.CSV.Tests │ ├── packages.config │ ├── FakeFileLoader.cs │ ├── TestData.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── CSVRepositoryTests.cs │ └── PersonRepository.CSV.Tests.csproj ├── PeopleViewer.Presentation.Tests │ ├── packages.config │ ├── FakeRepository.cs │ ├── PeopleViewModelTests.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── PeopleViewer.Presentation.Tests.csproj ├── PersonRepository.CSV │ ├── PersonRepository.CSV.csproj │ ├── CSVFileLoader.cs │ └── CSVRepository.cs ├── PersonRepository.Caching │ ├── PersonRepository.Caching.csproj │ └── CachingRepository.cs ├── AdditionalFiles │ └── People.txt ├── PeopleViewer.Presentation │ ├── PeopleViewer.Presentation.csproj │ └── PeopleViewModel.cs ├── PersonRepository.Service │ ├── PersonRepository.Service.csproj │ └── ServiceRepository.cs └── LooseCoupling.sln ├── TightCoupling ├── People.Service │ ├── appsettings.json │ ├── appsettings.Development.json │ ├── Models │ │ ├── IPeopleProvider.cs │ │ └── StaticPeopleProvider.cs │ ├── Program.cs │ ├── People.Service.csproj │ ├── Properties │ │ └── launchSettings.json │ ├── Controllers │ │ └── PeopleController.cs │ └── Startup.cs ├── PeopleViewer │ ├── packages.config │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml.cs │ ├── MainWindow.xaml.cs │ ├── MainWindow.xaml │ ├── Converters.cs │ └── PeopleViewer.csproj ├── Common │ ├── Common.csproj │ └── Person.cs ├── PeopleViewer.Presentation │ ├── PeopleViewer.Presentation.csproj │ └── PeopleViewModel.cs ├── PersonRepository.Service │ ├── PersonRepository.Service.csproj │ └── ServiceRepository.cs └── TightCoupling.sln ├── README.md ├── .gitattributes └── .gitignore /SLIDES-DependencyInjection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremybytes/learning-dependency-injection/HEAD/SLIDES-DependencyInjection.pdf -------------------------------------------------------------------------------- /LooseCoupling/People.Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /LooseCoupling/LateBindingAssemblies/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremybytes/learning-dependency-injection/HEAD/LooseCoupling/LateBindingAssemblies/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /LooseCoupling/LateBindingAssemblies/PersonRepository.CSV.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremybytes/learning-dependency-injection/HEAD/LooseCoupling/LateBindingAssemblies/PersonRepository.CSV.dll -------------------------------------------------------------------------------- /LooseCoupling/Common/Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TightCoupling/Common/Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LooseCoupling/LateBindingAssemblies/PersonRepository.Service.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremybytes/learning-dependency-injection/HEAD/LooseCoupling/LateBindingAssemblies/PersonRepository.Service.dll -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Models/IPeopleProvider.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System.Collections.Generic; 3 | 4 | namespace People.Service.Models 5 | { 6 | public interface IPeopleProvider 7 | { 8 | List GetPeople(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/Models/IPeopleProvider.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System.Collections.Generic; 3 | 4 | namespace People.Service.Models 5 | { 6 | public interface IPeopleProvider 7 | { 8 | List GetPeople(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LooseCoupling/Common/IPersonRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Common 5 | { 6 | public interface IPersonRepository 7 | { 8 | IEnumerable GetPeople(); 9 | Person GetPerson(int id); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV/PersonRepository.CSV.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.Caching/PersonRepository.Caching.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LooseCoupling/AdditionalFiles/People.txt: -------------------------------------------------------------------------------- 1 | 1,John,Koenig,1975/10/17,6, 2 | 2,Dylan,Hunt,2000/10/02,8, 3 | 3,Leela,Turanga,1999/3/28,8,{1} {0} 4 | 4,John,Crichton,1999/03/19,7, 5 | 5,Dave,Lister,1988/02/15,9, 6 | 6,Laura,Roslin,2003/12/8,6, 7 | 7,John,Sheridan,1994/01/26,6, 8 | 8,Dante,Montana,2000/11/01,5, 9 | 9,Isaac,Gampu,1977/09/10,4, 10 | 10,Jeremy,Awesome,1971/05/03,10, -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/autofac.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": [ 3 | { 4 | "type": "PersonRepository.Service.ServiceRepository, PersonRepository.Service", 5 | "services": [ 6 | { 7 | "type": "Common.IPersonRepository, Common" 8 | } 9 | ], 10 | "injectionProperties": false 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace PeopleViewer 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation/PeopleViewer.Presentation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer.Presentation/PeopleViewer.Presentation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.Service/PersonRepository.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /TightCoupling/PersonRepository.Service/PersonRepository.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace People.Service 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 14 | WebHost.CreateDefaultBuilder(args) 15 | .UseStartup() 16 | .UseUrls("http://localhost:9874"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace People.Service 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 14 | WebHost.CreateDefaultBuilder(args) 15 | .UseStartup() 16 | .UseUrls("http://localhost:9874"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/People.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | InProcess 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/People.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | InProcess 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LooseCoupling/Common/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Common 4 | { 5 | public class Person 6 | { 7 | public int Id { get; set; } 8 | public string GivenName { get; set; } 9 | public string FamilyName { get; set; } 10 | public DateTime StartDate { get; set; } 11 | public int Rating { get; set; } 12 | public string FormatString { get; set; } 13 | 14 | public override string ToString() 15 | { 16 | if (string.IsNullOrEmpty(FormatString)) 17 | FormatString = "{0} {1}"; 18 | return string.Format(FormatString, GivenName, FamilyName); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TightCoupling/Common/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Common 4 | { 5 | public class Person 6 | { 7 | public int Id { get; set; } 8 | public string GivenName { get; set; } 9 | public string FamilyName { get; set; } 10 | public DateTime StartDate { get; set; } 11 | public int Rating { get; set; } 12 | public string FormatString { get; set; } 13 | 14 | public override string ToString() 15 | { 16 | if (string.IsNullOrEmpty(FormatString)) 17 | FormatString = "{0} {1}"; 18 | return string.Format(FormatString, GivenName, FamilyName); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | learning-dependency-injection 2 | ============================= 3 | 4 | Many of our modern frameworks have Dependency Injection (DI) built in. But how do we use that effectively? We'll look at what DI is and why we want to use it. We'll see the problems caused by tight coupling. Then we'll use some DI patterns such as constructor injection and property injection to break that tight coupling. We'll see how loosely-coupled applications are easier to extend and test. With a better understanding of the basic patterns, we'll remove the magic behind DI containers so that we can use the tools appropriately in our code. 5 | 6 | Articles discribing the code are collected here: http://www.jeremybytes.com/Demos.aspx#DI 7 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using System.Windows; 3 | 4 | namespace PeopleViewer 5 | { 6 | public partial class MainWindow : Window 7 | { 8 | PeopleViewModel ViewModel { get; set; } 9 | 10 | public MainWindow(PeopleViewModel viewModel) 11 | { 12 | InitializeComponent(); 13 | ViewModel = viewModel; 14 | DataContext = ViewModel; 15 | } 16 | 17 | private void RefreshButton_Click(object sender, RoutedEventArgs e) 18 | { 19 | ViewModel.RefreshPeople(); 20 | } 21 | 22 | private void ClearButton_Click(object sender, RoutedEventArgs e) 23 | { 24 | ViewModel.ClearPeople(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using System.Windows; 3 | 4 | namespace PeopleViewer.Autofac 5 | { 6 | public partial class MainWindow : Window 7 | { 8 | PeopleViewModel ViewModel { get; set; } 9 | 10 | public MainWindow(PeopleViewModel viewModel) 11 | { 12 | InitializeComponent(); 13 | ViewModel = viewModel; 14 | DataContext = ViewModel; 15 | } 16 | 17 | private void RefreshButton_Click(object sender, RoutedEventArgs e) 18 | { 19 | ViewModel.RefreshPeople(); 20 | } 21 | 22 | private void ClearButton_Click(object sender, RoutedEventArgs e) 23 | { 24 | ViewModel.ClearPeople(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV/CSVFileLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace PersonRepository.CSV 7 | { 8 | public interface ICSVFileLoader 9 | { 10 | string LoadFile(); 11 | } 12 | 13 | public class CSVFileLoader : ICSVFileLoader 14 | { 15 | private string filePath; 16 | 17 | public CSVFileLoader(string filePath) 18 | { 19 | this.filePath = filePath; 20 | } 21 | 22 | public string LoadFile() 23 | { 24 | using (var reader = new StreamReader(filePath)) 25 | { 26 | string fileData = reader.ReadToEnd(); 27 | return fileData; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV.Tests/FakeFileLoader.cs: -------------------------------------------------------------------------------- 1 | namespace PersonRepository.CSV.Tests 2 | { 3 | public class FakeFileLoader : ICSVFileLoader 4 | { 5 | private string dataType; 6 | 7 | public FakeFileLoader(string dataType) 8 | { 9 | this.dataType = dataType; 10 | } 11 | 12 | public string LoadFile() 13 | { 14 | switch (dataType) 15 | { 16 | case "Good": return TestData.WithGoodRecords; 17 | case "Mixed": return TestData.WithGoodAndBadRecords; 18 | case "Bad": return TestData.WithOnlyBadRecords; 19 | case "Empty": return string.Empty; 20 | default: return TestData.WithGoodRecords; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using System.Windows; 3 | 4 | namespace PeopleViewer.Autofac.LateBinding 5 | { 6 | public partial class MainWindow : Window 7 | { 8 | PeopleViewModel ViewModel { get; set; } 9 | 10 | public MainWindow(PeopleViewModel viewModel) 11 | { 12 | InitializeComponent(); 13 | ViewModel = viewModel; 14 | DataContext = ViewModel; 15 | } 16 | 17 | private void RefreshButton_Click(object sender, RoutedEventArgs e) 18 | { 19 | ViewModel.RefreshPeople(); 20 | } 21 | 22 | private void ClearButton_Click(object sender, RoutedEventArgs e) 23 | { 24 | ViewModel.ClearPeople(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV.Tests/TestData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PersonRepository.CSV.Tests 4 | { 5 | public static class TestData 6 | { 7 | public static string WithGoodRecords = 8 | "1,John,Koenig,1975/10/17,6," + Environment.NewLine + 9 | "3,Leela,Turanga,1999/3/28,8,{1} {0}" + Environment.NewLine; 10 | 11 | public static string WithGoodAndBadRecords = 12 | "1,John,Koenig,1975/10/17,6," + Environment.NewLine + 13 | "INVALID DATA" + Environment.NewLine + 14 | "3,Leela,Turanga,1999/3/28,8,{1} {0}" + Environment.NewLine + 15 | "MORE INVALID DATA" + Environment.NewLine; 16 | 17 | public static string WithOnlyBadRecords = 18 | "INVALID DATA" + Environment.NewLine + 19 | "MORE INVALID DATA" + Environment.NewLine; 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using PersonRepository.Caching; 3 | using PersonRepository.CSV; 4 | using PersonRepository.Service; 5 | using System.Windows; 6 | 7 | namespace PeopleViewer 8 | { 9 | public partial class App : Application 10 | { 11 | protected override void OnStartup(StartupEventArgs e) 12 | { 13 | base.OnStartup(e); 14 | ComposeObjects(); 15 | Application.Current.MainWindow.Show(); 16 | } 17 | 18 | private static void ComposeObjects() 19 | { 20 | var wrappeRepo = new ServiceRepository(); 21 | var repository = new CachingRepository(wrappeRepo); 22 | var viewModel = new PeopleViewModel(repository); 23 | Application.Current.MainWindow = new MainWindow(viewModel); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:32101", 8 | "sslPort": 44340 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/values", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "People.Service": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "api/values", 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /TightCoupling/People.Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:32101", 8 | "sslPort": 44340 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/values", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "People.Service": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "api/values", 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Controllers/PeopleController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.AspNetCore.Mvc; 4 | using People.Service.Models; 5 | using Common; 6 | 7 | namespace People.Service.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class PeopleController : ControllerBase 12 | { 13 | IPeopleProvider provider; 14 | 15 | public PeopleController(IPeopleProvider provider) 16 | { 17 | this.provider = provider; 18 | } 19 | 20 | // GET api/values 21 | [HttpGet] 22 | public IEnumerable Get() 23 | { 24 | return provider.GetPeople(); 25 | } 26 | 27 | // GET api/values/5 28 | [HttpGet("{id}")] 29 | public Person Get(int id) 30 | { 31 | return provider.GetPeople().FirstOrDefault(p => p.Id == id); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /TightCoupling/People.Service/Controllers/PeopleController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.AspNetCore.Mvc; 4 | using People.Service.Models; 5 | using Common; 6 | 7 | namespace People.Service.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class PeopleController : ControllerBase 12 | { 13 | IPeopleProvider provider; 14 | 15 | public PeopleController(IPeopleProvider provider) 16 | { 17 | this.provider = provider; 18 | } 19 | 20 | // GET api/values 21 | [HttpGet] 22 | public IEnumerable Get() 23 | { 24 | return provider.GetPeople(); 25 | } 26 | 27 | // GET api/values/5 28 | [HttpGet("{id}")] 29 | public Person Get(int id) 30 | { 31 | return provider.GetPeople().FirstOrDefault(p => p.Id == id); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /TightCoupling/PersonRepository.Service/ServiceRepository.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using Newtonsoft.Json; 3 | using System.Collections.Generic; 4 | using System.Net; 5 | 6 | namespace PersonRepository.Service 7 | { 8 | public class ServiceRepository 9 | { 10 | private WebClient client; 11 | private string baseUri; 12 | 13 | public ServiceRepository() 14 | { 15 | client = new WebClient(); 16 | baseUri = "http://localhost:9874/"; 17 | } 18 | 19 | public IEnumerable GetPeople() 20 | { 21 | var address = $"{baseUri}api/people"; 22 | string reply = client.DownloadString(address); 23 | return JsonConvert.DeserializeObject>(reply); 24 | } 25 | 26 | public Person GetPerson(int id) 27 | { 28 | var address = $"{baseUri}api/people/{id}"; 29 | string reply = client.DownloadString(address); 30 | return JsonConvert.DeserializeObject(reply); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.Service/ServiceRepository.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using Newtonsoft.Json; 3 | using System.Collections.Generic; 4 | using System.Net; 5 | 6 | namespace PersonRepository.Service 7 | { 8 | public class ServiceRepository : IPersonRepository 9 | { 10 | WebClient client; 11 | string baseUri; 12 | 13 | public ServiceRepository() 14 | { 15 | client = new WebClient(); 16 | baseUri = "http://localhost:9874/"; 17 | } 18 | 19 | public IEnumerable GetPeople() 20 | { 21 | var address = $"{baseUri}api/people"; 22 | string reply = client.DownloadString(address); 23 | return JsonConvert.DeserializeObject>(reply); 24 | } 25 | 26 | public Person GetPerson(int id) 27 | { 28 | var address = $"{baseUri}api/people/{id}"; 29 | string reply = client.DownloadString(address); 30 | return JsonConvert.DeserializeObject(reply); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation.Tests/FakeRepository.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace PeopleViewer.Presentation.Tests 8 | { 9 | public class FakeRepository : IPersonRepository 10 | { 11 | 12 | public IEnumerable GetPeople() 13 | { 14 | var people = new List() 15 | { 16 | new Person() {Id = 1, 17 | GivenName = "John", FamilyName = "Smith", 18 | Rating = 7, StartDate = new DateTime(2000, 10, 1)}, 19 | new Person() {Id = 2, 20 | GivenName = "Mary", FamilyName = "Thomas", 21 | Rating = 9, StartDate = new DateTime(1971, 7, 23)}, 22 | }; 23 | 24 | return people; 25 | } 26 | 27 | public Person GetPerson(int id) 28 | { 29 | var people = GetPeople(); 30 | return people.FirstOrDefault(p => p.Id == id); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using Ninject; 3 | using PersonRepository.Caching; 4 | using PersonRepository.CSV; 5 | using PersonRepository.Service; 6 | using System.Windows; 7 | 8 | namespace PeopleViewer.Ninject 9 | { 10 | public partial class App : Application 11 | { 12 | IKernel Container; 13 | 14 | protected override void OnStartup(StartupEventArgs e) 15 | { 16 | base.OnStartup(e); 17 | ConfigureContainer(); 18 | ComposeObjects(); 19 | Application.Current.MainWindow.Show(); 20 | } 21 | 22 | private void ConfigureContainer() 23 | { 24 | Container = new StandardKernel(); 25 | Container.Bind().To() 26 | .InSingletonScope() 27 | .WithConstructorArgument( 28 | Container.Get()); 29 | } 30 | 31 | private void ComposeObjects() 32 | { 33 | Application.Current.MainWindow = Container.Get(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace PeopleViewer 18 | { 19 | public partial class MainWindow : Window 20 | { 21 | PeopleViewModel ViewModel { get; set; } 22 | 23 | public MainWindow() 24 | { 25 | InitializeComponent(); 26 | ViewModel = new PeopleViewModel(); 27 | DataContext = ViewModel; 28 | } 29 | 30 | private void RefreshButton_Click(object sender, RoutedEventArgs e) 31 | { 32 | ViewModel.RefreshPeople(); 33 | } 34 | 35 | private void ClearButton_Click(object sender, RoutedEventArgs e) 36 | { 37 | ViewModel.ClearPeople(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using PeopleViewer.Presentation; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace PeopleViewer.Ninject 18 | { 19 | public partial class MainWindow : Window 20 | { 21 | PeopleViewModel ViewModel { get; set; } 22 | 23 | public MainWindow(PeopleViewModel viewModel) 24 | { 25 | InitializeComponent(); 26 | ViewModel = viewModel; 27 | DataContext = ViewModel; 28 | } 29 | 30 | private void RefreshButton_Click(object sender, RoutedEventArgs e) 31 | { 32 | ViewModel.RefreshPeople(); 33 | } 34 | 35 | private void ClearButton_Click(object sender, RoutedEventArgs e) 36 | { 37 | ViewModel.ClearPeople(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PeopleViewer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PeopleViewer.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PeopleViewer.Autofac.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PeopleViewer.Ninject.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PeopleViewer.Autofac.LateBinding.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using People.Service.Models; 7 | 8 | namespace People.Service 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 23 | services.AddSingleton(); 24 | } 25 | 26 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 27 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 28 | { 29 | if (env.IsDevelopment()) 30 | { 31 | app.UseDeveloperExceptionPage(); 32 | } 33 | app.UseMvc(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using People.Service.Models; 7 | 8 | namespace People.Service 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 23 | services.AddSingleton(); 24 | } 25 | 26 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 27 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 28 | { 29 | if (env.IsDevelopment()) 30 | { 31 | app.UseDeveloperExceptionPage(); 32 | } 33 | app.UseMvc(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation.Tests/PeopleViewModelTests.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using NUnit.Framework; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace PeopleViewer.Presentation.Tests 7 | { 8 | public class PeopleViewModelTests 9 | { 10 | private IPersonRepository GetTestRepository() 11 | { 12 | return new FakeRepository(); 13 | } 14 | 15 | [Test] 16 | public void RefreshPeople_OnExecute_PeopleIsPopulated() 17 | { 18 | // Arrange 19 | var repository = GetTestRepository(); 20 | var vm = new PeopleViewModel(repository); 21 | 22 | // Act 23 | vm.RefreshPeople(); 24 | 25 | // Assert 26 | Assert.IsNotNull(vm.People); 27 | Assert.AreEqual(2, vm.People.Count()); 28 | } 29 | 30 | [Test] 31 | public void ClearPeople_OnExecute_PeopleIsEmpty() 32 | { 33 | // Arrange 34 | var repository = GetTestRepository(); 35 | var vm = new PeopleViewModel(repository); 36 | vm.RefreshPeople(); 37 | Assert.AreEqual(2, vm.People.Count(), "Invalid Arrangement"); 38 | 39 | // Act 40 | vm.ClearPeople(); 41 | 42 | // Assert 43 | Assert.AreEqual(0, vm.People.Count()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation/PeopleViewModel.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace PeopleViewer.Presentation 6 | { 7 | public class PeopleViewModel : INotifyPropertyChanged 8 | { 9 | protected IPersonRepository Repository; 10 | 11 | private IEnumerable _people; 12 | public IEnumerable People 13 | { 14 | get { return _people; } 15 | set 16 | { 17 | if (_people == value) 18 | return; 19 | _people = value; 20 | RaisePropertyChanged("People"); 21 | } 22 | } 23 | 24 | public PeopleViewModel(IPersonRepository repository) 25 | { 26 | Repository = repository; 27 | } 28 | 29 | public void RefreshPeople() 30 | { 31 | People = Repository.GetPeople(); 32 | } 33 | 34 | public void ClearPeople() 35 | { 36 | People = new List(); 37 | } 38 | 39 | #region INotifyPropertyChanged Members 40 | 41 | public event PropertyChangedEventHandler PropertyChanged; 42 | private void RaisePropertyChanged(string propertyName) 43 | { 44 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 45 | } 46 | 47 | #endregion 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Autofac.Configuration; 3 | using Microsoft.Extensions.Configuration; 4 | using PeopleViewer.Presentation; 5 | using System.Windows; 6 | 7 | namespace PeopleViewer.Autofac.LateBinding 8 | { 9 | public partial class App : Application 10 | { 11 | IContainer Container; 12 | 13 | protected override void OnStartup(StartupEventArgs e) 14 | { 15 | base.OnStartup(e); 16 | ConfigureContainer(); 17 | ComposeObjects(); 18 | Application.Current.MainWindow.Title = "With Dependency Injection - Autofac Late Binding"; 19 | Application.Current.MainWindow.Show(); 20 | } 21 | 22 | private void ConfigureContainer() 23 | { 24 | var config = new ConfigurationBuilder(); 25 | config.AddJsonFile("autofac.json"); 26 | 27 | var module = new ConfigurationModule(config.Build()); 28 | var builder = new ContainerBuilder(); 29 | builder.RegisterModule(module); 30 | 31 | builder.RegisterType().InstancePerDependency(); 32 | builder.RegisterType().InstancePerDependency(); 33 | 34 | Container = builder.Build(); 35 | } 36 | 37 | private void ComposeObjects() 38 | { 39 | Application.Current.MainWindow = Container.Resolve(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer.Presentation/PeopleViewModel.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using PersonRepository.Service; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Threading.Tasks; 7 | 8 | namespace PeopleViewer.Presentation 9 | { 10 | public class PeopleViewModel : INotifyPropertyChanged 11 | { 12 | protected ServiceRepository Repository; 13 | 14 | private IEnumerable _people; 15 | public IEnumerable People 16 | { 17 | get { return _people; } 18 | set 19 | { 20 | if (_people == value) 21 | return; 22 | _people = value; 23 | RaisePropertyChanged("People"); 24 | } 25 | } 26 | 27 | public PeopleViewModel() 28 | { 29 | Repository = new ServiceRepository(); 30 | } 31 | 32 | public void RefreshPeople() 33 | { 34 | People = Repository.GetPeople(); 35 | } 36 | 37 | public void ClearPeople() 38 | { 39 | People = new List(); 40 | } 41 | 42 | #region INotifyPropertyChanged Members 43 | 44 | public event PropertyChangedEventHandler PropertyChanged; 45 | private void RaisePropertyChanged(string propertyName) 46 | { 47 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 48 | } 49 | 50 | #endregion 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PersonRepository.CSV.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PersonRepository.CSV.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cb1bfab0-7133-44b2-83b3-1e0c3637e6ce")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Presentation.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PeopleViewer.Presentation.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PeopleViewer.Presentation.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8bb096f4-1db0-4038-ba69-a4f75406d336")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /LooseCoupling/People.Service/Models/StaticPeopleProvider.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace People.Service.Models 6 | { 7 | public class StaticPeopleProvider : IPeopleProvider 8 | { 9 | public List GetPeople() 10 | { 11 | var p = new List() 12 | { 13 | new Person() { Id=1, GivenName="John", FamilyName="Koenig", 14 | StartDate = new DateTime(1975, 10, 17), Rating=6 }, 15 | new Person() { Id=2, GivenName="Dylan", FamilyName="Hunt", 16 | StartDate = new DateTime(2000, 10, 2), Rating=8 }, 17 | new Person() { Id=3, GivenName="Leela", FamilyName="Turanga", 18 | StartDate = new DateTime(1999, 3, 28), Rating=8, 19 | FormatString = "{1} {0}" }, 20 | new Person() { Id=4, GivenName="John", FamilyName="Crichton", 21 | StartDate = new DateTime(1999, 3, 19), Rating=7 }, 22 | new Person() { Id=5, GivenName="Dave", FamilyName="Lister", 23 | StartDate = new DateTime(1988, 2, 15), Rating=9 }, 24 | new Person() { Id=6, GivenName="Laura", FamilyName="Roslin", 25 | StartDate = new DateTime(2003, 12, 8), Rating=6}, 26 | new Person() { Id=7, GivenName="John", FamilyName="Sheridan", 27 | StartDate = new DateTime(1994, 1, 26), Rating=6 }, 28 | new Person() { Id=8, GivenName="Dante", FamilyName="Montana", 29 | StartDate = new DateTime(2000, 11, 1), Rating=5 }, 30 | new Person() { Id=9, GivenName="Isaac", FamilyName="Gampu", 31 | StartDate = new DateTime(1977, 9, 10), Rating=4 }, 32 | }; 33 | return p; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TightCoupling/People.Service/Models/StaticPeopleProvider.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace People.Service.Models 6 | { 7 | public class StaticPeopleProvider : IPeopleProvider 8 | { 9 | public List GetPeople() 10 | { 11 | var p = new List() 12 | { 13 | new Person() { Id=1, GivenName="John", FamilyName="Koenig", 14 | StartDate = new DateTime(1975, 10, 17), Rating=6 }, 15 | new Person() { Id=2, GivenName="Dylan", FamilyName="Hunt", 16 | StartDate = new DateTime(2000, 10, 2), Rating=8 }, 17 | new Person() { Id=3, GivenName="Leela", FamilyName="Turanga", 18 | StartDate = new DateTime(1999, 3, 28), Rating=8, 19 | FormatString = "{1} {0}" }, 20 | new Person() { Id=4, GivenName="John", FamilyName="Crichton", 21 | StartDate = new DateTime(1999, 3, 19), Rating=7 }, 22 | new Person() { Id=5, GivenName="Dave", FamilyName="Lister", 23 | StartDate = new DateTime(1988, 2, 15), Rating=9 }, 24 | new Person() { Id=6, GivenName="Laura", FamilyName="Roslin", 25 | StartDate = new DateTime(2003, 12, 8), Rating=6}, 26 | new Person() { Id=7, GivenName="John", FamilyName="Sheridan", 27 | StartDate = new DateTime(1994, 1, 26), Rating=6 }, 28 | new Person() { Id=8, GivenName="Dante", FamilyName="Montana", 29 | StartDate = new DateTime(2000, 11, 1), Rating=5 }, 30 | new Person() { Id=9, GivenName="Isaac", FamilyName="Gampu", 31 | StartDate = new DateTime(1977, 9, 10), Rating=4 }, 32 | }; 33 | return p; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LooseCoupling/LateBindingAssemblies/PersonRepository.CSV.deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeTarget": { 3 | "name": ".NETStandard,Version=v2.0/", 4 | "signature": "" 5 | }, 6 | "compilationOptions": {}, 7 | "targets": { 8 | ".NETStandard,Version=v2.0": {}, 9 | ".NETStandard,Version=v2.0/": { 10 | "PersonRepository.CSV/1.0.0": { 11 | "dependencies": { 12 | "Common": "1.0.0", 13 | "NETStandard.Library": "2.0.3" 14 | }, 15 | "runtime": { 16 | "PersonRepository.CSV.dll": {} 17 | } 18 | }, 19 | "Microsoft.NETCore.Platforms/1.1.0": {}, 20 | "NETStandard.Library/2.0.3": { 21 | "dependencies": { 22 | "Microsoft.NETCore.Platforms": "1.1.0" 23 | } 24 | }, 25 | "Common/1.0.0": { 26 | "runtime": { 27 | "Common.dll": {} 28 | } 29 | } 30 | } 31 | }, 32 | "libraries": { 33 | "PersonRepository.CSV/1.0.0": { 34 | "type": "project", 35 | "serviceable": false, 36 | "sha512": "" 37 | }, 38 | "Microsoft.NETCore.Platforms/1.1.0": { 39 | "type": "package", 40 | "serviceable": true, 41 | "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", 42 | "path": "microsoft.netcore.platforms/1.1.0", 43 | "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" 44 | }, 45 | "NETStandard.Library/2.0.3": { 46 | "type": "package", 47 | "serviceable": true, 48 | "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", 49 | "path": "netstandard.library/2.0.3", 50 | "hashPath": "netstandard.library.2.0.3.nupkg.sha512" 51 | }, 52 | "Common/1.0.0": { 53 | "type": "project", 54 | "serviceable": false, 55 | "sha512": "" 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Autofac.Features.ResolveAnything; 3 | using Common; 4 | using PeopleViewer.Presentation; 5 | using PersonRepository.Caching; 6 | using PersonRepository.Service; 7 | using PersonRepository.CSV; 8 | using System.Windows; 9 | 10 | namespace PeopleViewer.Autofac 11 | { 12 | public partial class App : Application 13 | { 14 | IContainer Container; 15 | 16 | protected override void OnStartup(StartupEventArgs e) 17 | { 18 | base.OnStartup(e); 19 | ConfigureContainer(); 20 | ComposeObjects(); 21 | Application.Current.MainWindow.Title = "With Dependency Injection - Autofac"; 22 | Application.Current.MainWindow.Show(); 23 | } 24 | 25 | private void ConfigureContainer() 26 | { 27 | var builder = new ContainerBuilder(); 28 | 29 | // DATA READER TYPE OPTION #1 - No Decorator 30 | //builder.RegisterType().As() 31 | // .SingleInstance(); 32 | 33 | // DATA READER TYPE OPTION #2 - With Decorator 34 | builder.RegisterType().Named("repository") 35 | .SingleInstance(); 36 | builder.RegisterDecorator( 37 | (c, inner) => new CachingRepository(inner), fromKey: "repository"); 38 | 39 | // OTHER TYPES OPTION #1 - Automatic Registration 40 | //builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); 41 | 42 | // OTHER TYPES OPTION #2 - Explicit Registration 43 | builder.RegisterType().InstancePerDependency(); 44 | builder.RegisterType().InstancePerDependency(); 45 | 46 | Container = builder.Build(); 47 | } 48 | 49 | private void ComposeObjects() 50 | { 51 | Application.Current.MainWindow = Container.Resolve(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.Caching/CachingRepository.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using System.Linq; 6 | 7 | namespace PersonRepository.Caching 8 | { 9 | public class CachingRepository : IPersonRepository 10 | { 11 | private TimeSpan _cacheDuration = new TimeSpan(0, 0, 30); 12 | private DateTime _dataDateTime; 13 | private IPersonRepository _wrappedRepository; 14 | private IEnumerable _cachedItems; 15 | 16 | public CachingRepository(IPersonRepository wrappedPersonRepository) 17 | { 18 | _wrappedRepository = wrappedPersonRepository; 19 | } 20 | 21 | private bool IsCacheValid 22 | { 23 | get 24 | { 25 | var _cacheAge = DateTime.Now - _dataDateTime; 26 | return _cacheAge < _cacheDuration; 27 | } 28 | } 29 | 30 | private void ValidateCache() 31 | { 32 | if (_cachedItems == null || !IsCacheValid) 33 | { 34 | try 35 | { 36 | _cachedItems = _wrappedRepository.GetPeople(); 37 | _dataDateTime = DateTime.Now; 38 | } 39 | catch 40 | { 41 | _cachedItems = new List() 42 | { 43 | new Person(){ GivenName = "No Data Available", FamilyName = string.Empty, Rating = 0, StartDate = DateTime.Today}, 44 | }; 45 | } 46 | } 47 | } 48 | 49 | private void InvalidateCache() 50 | { 51 | _dataDateTime = DateTime.MinValue; 52 | } 53 | 54 | public IEnumerable GetPeople() 55 | { 56 | ValidateCache(); 57 | return _cachedItems; 58 | } 59 | 60 | public Person GetPerson(int id) 61 | { 62 | ValidateCache(); 63 | return _cachedItems.FirstOrDefault(p => p.Id == id); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV.Tests/CSVRepositoryTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace PersonRepository.CSV.Tests 7 | { 8 | public class CSVRepositoryTests 9 | { 10 | [Test] 11 | public void GetPeople_WithEmptyFile_ReturnsEmptyList() 12 | { 13 | var repository = new CSVRepository(); 14 | repository.FileLoader = new FakeFileLoader("Empty"); 15 | 16 | var result = repository.GetPeople(); 17 | 18 | Assert.IsEmpty(result); 19 | } 20 | 21 | [Test] 22 | public void GetTask_WithNoFile_ThrowsFileNotFoundException() 23 | { 24 | var repository = new CSVRepository(); 25 | 26 | try 27 | { 28 | var result = repository.GetPeople(); 29 | Assert.Fail(); 30 | } 31 | catch (FileNotFoundException) 32 | { 33 | Assert.Pass(); 34 | } 35 | } 36 | 37 | [Test] 38 | public void GetPeople_WithGoodRecords_ReturnsGoodRecords() 39 | { 40 | var repository = new CSVRepository(); 41 | repository.FileLoader = new FakeFileLoader("Good"); 42 | 43 | var result = repository.GetPeople(); 44 | 45 | Assert.AreEqual(2, result.Count()); 46 | } 47 | 48 | [Test] 49 | public void GetPeople_WithBadRecords_ReturnsGoodRecords() 50 | { 51 | var repository = new CSVRepository(); 52 | repository.FileLoader = new FakeFileLoader("Mixed"); 53 | 54 | var result = repository.GetPeople(); 55 | 56 | Assert.AreEqual(2, result.Count()); 57 | } 58 | 59 | [Test] 60 | public void GetPeople_WithOnlyBadRecord_ReturnsEmptyList() 61 | { 62 | var repository = new CSVRepository(); 63 | repository.FileLoader = new FakeFileLoader("Bad"); 64 | 65 | var result = repository.GetPeople(); 66 | 67 | Assert.IsEmpty(result); 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /LooseCoupling/PersonRepository.CSV/CSVRepository.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace PersonRepository.CSV 7 | { 8 | public class CSVRepository : IPersonRepository 9 | { 10 | public ICSVFileLoader FileLoader { get; set; } 11 | 12 | public CSVRepository() 13 | { 14 | string filePath = AppDomain.CurrentDomain.BaseDirectory + "People.txt"; 15 | FileLoader = new CSVFileLoader(filePath); 16 | } 17 | 18 | public IEnumerable GetPeople() 19 | { 20 | var fileData = FileLoader.LoadFile(); 21 | var people = ParseString(fileData); 22 | return people; 23 | } 24 | 25 | public Person GetPerson(int id) 26 | { 27 | var people = GetPeople(); 28 | return people?.FirstOrDefault(p => p.Id == id); 29 | } 30 | 31 | private List ParseString(string csvData) 32 | { 33 | var people = new List(); 34 | 35 | var lines = csvData.Split(new[] { Environment.NewLine }, StringSplitOptions.None); 36 | 37 | foreach (string line in lines) 38 | { 39 | try 40 | { 41 | var elems = line.Split(','); 42 | var per = new Person() 43 | { 44 | Id = Int32.Parse(elems[0]), 45 | GivenName = elems[1], 46 | FamilyName = elems[2], 47 | StartDate = DateTime.Parse(elems[3]), 48 | Rating = Int32.Parse(elems[4]), 49 | FormatString = elems[5], 50 | }; 51 | people.Add(per); 52 | } 53 | catch (Exception) 54 | { 55 | // Skip the bad record, log it, and move to the next record 56 | // log.write("Unable to parse record", per); 57 | } 58 | } 59 | return people; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LooseCoupling/LateBindingAssemblies/PersonRepository.Service.deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeTarget": { 3 | "name": ".NETStandard,Version=v2.0/", 4 | "signature": "" 5 | }, 6 | "compilationOptions": {}, 7 | "targets": { 8 | ".NETStandard,Version=v2.0": {}, 9 | ".NETStandard,Version=v2.0/": { 10 | "PersonRepository.Service/1.0.0": { 11 | "dependencies": { 12 | "Common": "1.0.0", 13 | "NETStandard.Library": "2.0.3", 14 | "Newtonsoft.Json": "11.0.2" 15 | }, 16 | "runtime": { 17 | "PersonRepository.Service.dll": {} 18 | } 19 | }, 20 | "Microsoft.NETCore.Platforms/1.1.0": {}, 21 | "NETStandard.Library/2.0.3": { 22 | "dependencies": { 23 | "Microsoft.NETCore.Platforms": "1.1.0" 24 | } 25 | }, 26 | "Newtonsoft.Json/11.0.2": { 27 | "runtime": { 28 | "lib/netstandard2.0/Newtonsoft.Json.dll": { 29 | "assemblyVersion": "11.0.0.0", 30 | "fileVersion": "11.0.2.21924" 31 | } 32 | } 33 | }, 34 | "Common/1.0.0": { 35 | "runtime": { 36 | "Common.dll": {} 37 | } 38 | } 39 | } 40 | }, 41 | "libraries": { 42 | "PersonRepository.Service/1.0.0": { 43 | "type": "project", 44 | "serviceable": false, 45 | "sha512": "" 46 | }, 47 | "Microsoft.NETCore.Platforms/1.1.0": { 48 | "type": "package", 49 | "serviceable": true, 50 | "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", 51 | "path": "microsoft.netcore.platforms/1.1.0", 52 | "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" 53 | }, 54 | "NETStandard.Library/2.0.3": { 55 | "type": "package", 56 | "serviceable": true, 57 | "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", 58 | "path": "netstandard.library/2.0.3", 59 | "hashPath": "netstandard.library.2.0.3.nupkg.sha512" 60 | }, 61 | "Newtonsoft.Json/11.0.2": { 62 | "type": "package", 63 | "serviceable": true, 64 | "sha512": "sha512-IvJe1pj7JHEsP8B8J8DwlMEx8UInrs/x+9oVY+oCD13jpLu4JbJU2WCIsMRn5C4yW9+DgkaO8uiVE5VHKjpmdQ==", 65 | "path": "newtonsoft.json/11.0.2", 66 | "hashPath": "newtonsoft.json.11.0.2.nupkg.sha512" 67 | }, 68 | "Common/1.0.0": { 69 | "type": "project", 70 | "serviceable": false, 71 | "sha512": "" 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("PeopleViewer")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("PeopleViewer")] 15 | [assembly: AssemblyCopyright("Copyright © 2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /TightCoupling/PeopleViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("PeopleViewer")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("PeopleViewer")] 15 | [assembly: AssemblyCopyright("Copyright © 2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("PeopleViewer.Autofac")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("PeopleViewer.Autofac")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Ninject/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("PeopleViewer.Ninject")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("PeopleViewer.Ninject")] 15 | [assembly: AssemblyCopyright("Copyright © 2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer.Autofac.LateBinding/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("PeopleViewer.Autofac.LateBinding")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("PeopleViewer.Autofac.LateBinding")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /LooseCoupling/PeopleViewer/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |