45,59 €
Inject dependencies and write highly maintainable and flexible code using the new .NET Core DI Engine
C# and .NET developers who have no idea what DI is and would like to understand how to implement it in their applications.
.NET Core provides more control than ever over web application architectures. A key point of this software architecture is that it's based on the use of Dependency Injection as a way to properly implement the Dependency Inversion principle proposed in the SOLID principles established by Robert C. Martin.
With the advent of .NET Core, things have become much simpler with Dependency Injection built into the system. This book aims to give you a profound insight into writing loosely-coupled code using the latest features available in .NET Core. It talks about constructors, parameter, setters, and interface injection, explaining in detail, with the help of examples, which type of injection to use in which situation. It will show you how to implement a class that creates other classes with associated dependencies, also called IoC containers, and then create dependencies for each MVC component of ASP.NET Core. You'll learn to distinguish between IoC containers, the use of Inversion of Control, and DI itself, since DI is just a way of implementing IoC via these containers. You'll also learn how to build dependencies for other frontend tool such as Angular. You will get to use the in-built services offered by .NET Core to create your own custom dependencies.
Towards the end, we'll talk about some patterns and anti-patterns for Dependency Injection along with some techniques to refactor legacy applications and inject dependencies.
Filled with examples, this book will take you through various techniques for injecting dependencies into your applications with or without the use of frameworks.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 443
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: November 2017
Production reference: 1071117
ISBN 978-1-78712-130-0
www.packtpub.com
Authors
Marino Posadas
Tadit Dash
Copy Editor
Safis Editing
Reviewer
Gaurav Aroraa
Project Coordinator
Prajakta Naik
Commissioning Editor
Aaron Lazar
Proofreader
Safis Editing
Acquisition Editor
Denim Pinto
Indexer
Pratik Shirodkar
Content Development Editor
Lawrence Veigas
Graphics
Jason Monteiro
Technical Editor
Tiksha Sarang
Production Coordinator
Aparna Bhagat
Marino Posadas is an independent senior trainer, writer, and consultant in Microsoft Technologies and Web Standards. He is a Microsoft MVP in C#, Visual Studio, and Development Technologies; an MCT, MCPD, MCTS, MCAD, and MCSD; and he was the former Director of Development in Spain and Portugal for Solid Quality Mentors.
Marino has published 15 books and more than 500 articles on development technologies in several magazines and online publications. The topics covered in his books range from Clipper and Visual Basic 5.0/ 6.0 to C # and .NET- safe programming, programming with Silverlight 2.0 and 4.0, and Web Standards.
His latest books are Mastering C# and .NET Framework, by Packt, and The Guide to Programming in HTML5, CSS3, and JavaScript with Visual Studio. He is also a speaker at Microsoft events, having lectured in Spain, Portugal, England, the US, Costa Rica, and Mexico.
His website also contains developer's resources and videos, in English and Spanish, interviewing representatives of the Microsoft and Web Standards development world.
You can follow him on Twitter at @MarinoPosadas.
Tadit Dash is a software engineer by profession. As a software engineer, he usually works for 8 to 9 hours daily. Besides his daily work, he contributes to both online and offline communities. He co-founded the first technical community in his state, named Microsoft Developers Community Odisha, which is devoted to spreading awareness of the newest trends in technology among developers. This community organizes events and workshops in orphanages, schools, and colleges.
He writes articles and blogs and creates demos and videos for fellow programmers. Answering questions on online forums and social channels are the activities he enjoys the most. Due to his exceptional contribution to the technical community, Microsoft has awarded him with the Microsoft Most Valuable Professional accolade since 2014. CodeProject has awarded him the CodeProject MVP accolade (the first from Odisha and three times in a row for the years 2014, 2015, and 2016). For his constant mentorship, IndiaMentor featured him as a Young Mentor on their site.
He was recognized by DZone and awarded the Most Valuable Blogger accolade. He was awarded the Star and Achiever accolade from his organization. Motivating students in his sessions is something he is popular for. He is a regular technical and motivational speaker. He has spoken at many local events organized by different communities. He was a featured speaker in DevTechDay Nepal.
Gaurav Aroraa has his M.Phil in computer science. He is a Microsoft MVP, lifetime member of the Computer Society of India (CSI), Advisory member of IndiaMentor, certified scrum trainer/coach, XEN for ITIL-F and APMG for PRINCE-F and PRINCE-P. He is an Open Source developer, contributor to TechNet Wiki, and the founder of Innatus Curo Software LLC. For over 19 years of his career, he has mentored thousands of students and industry professionals. You can tweet Gaurav on his twitter handle at @g_arora.
He has authored the following books:
Building Microservices in ASP.NET Core, Packt Publishing
Learn C# in 7 Days,
Packt Publishing
SOLID Principles Succinctly, Syncfusion
ASP.NET WebHooks Succinctly
, Syncfusion
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/1787121305.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
The SOLID Principles of Software Design
In the beginning
.NET and .NET Core
About .NET Core
ASP.NET Core
About the IDE used in this book
Other foundational changes in .NET Core
The SOLID principles
The Single Responsibility Principle (SRP)
The background of the Separation of Concerns (SoC)
Well-known examples of Separation of Concerns
A basic sample of Separation of Concerns
Another sample
The Open/Closed principle
Back to our sample
The Liskov Substitution principle
Back to the code again
Other implementations of LSP in .NET
The Interface Segregation principle
Another sample
The Dependency Inversion principle
The (more or less) canonical example
Other ways to implement Dependency Inversion
Summary
Dependency Injection and IoC Containers
The Dependency Principle in more detail
Let's look at an example
Aspects of Dependency Injection
Object Composition
Object Lifetime
Interception
Ways to implement DI
Property Injection in action
Method Injection in practice
.NET event architecture as Model Injection
DI containers
Service locators
DI Containers for .NET
Using Unity Container
Using Castle Windsor
Using StructureMap
Using Autofac
Dependency Injection in other frameworks
DI in Angular
Our first demo
Summary
Introducing Dependency Injection in .NET Core 2.0
The main characteristics of .NET Core
The main advantages of .NET Core
Installation of .NET Core in the IDE
Installation path for .NET Core in Visual Studio 2015
.NET Core in Visual Studio 2017
Types of deployment
Checking other dependencies in .NET Core
Dependency Injection in .NET Core
DI Architecture and Object's Lifetime
The class ActivatorUtilities and other helpers
The Microsoft.Extensions.DependencyInjection container
Checking the object's lifetime
Mapping interfaces to instance classes
The concept of Scope Applied to services
Other extensions with DI functionality
A reflection on the structure of .NET Core
LogLevels Severity
Summary
Dependency Injection in ASP.NET Core
ASP.NET Core from the command-line tools
Creating the minimum possible application
Changing to ASP .NET Core
Middleware
The Startup class and Dependency Injection
Code explanation
The New ASP.NET servers
Kestrel
WebListener
Dependency Inversion in the architecture - OWIN
Analyzing the default template
Configuration files
The Entry Point
The default Startup class
Dependency Injection in ASP.NET Core
Services provided by ASP.NET Core
The relation of services available at startup
Identifying Services in the Web Application template
Using Dependency Injection in ASP.NET MVC Views
Garbage Collection and Custom Services
Using Custom Services through Dependency Injection
Services and data management
Using Dependency Injection inside Views
Summary
Object Composition
Understanding object relationships
Object Composition
Types of Object Composition
Composition
Consider an example
Contrasting features of Composition
Why are subclasses inside Composition?
Important notes
Aggregation
Consider an example
Composition versus Aggregation
Advantages and disadvantages
Other important relationships
Association
Example
Explanation of the preceding code
Types of Association
Reflexive Association
Indirect Association
Composition over Inheritance
Inheritance
Example on User class
New User Type
Problem which we come across
The solution to the problem
Role of Object Composition in Dependency Injection
Composition Root
Composing .NET Core 2.0 Console application
Object Composition in ASP.NET Core MVC 2.0
Summary
Object Lifetime
Manage the object life cycle
Stack versus heap
Managed and unmanaged resources
Generations
Object creation
The Copy constructor
Object destruction
Finalize
The IDisposable interface
Consider an example
Implementing the IDisposable Interface
Step1 - Basic structure of class
Step2 - Defining a Dispose Overload method
Step3 -Modifying the Dispose(bool) for Derived classes
Step 4 - Handling duplicate Dispose calls
Object lifetime management in .NET Core
Object creation
Designing the interfaces
The Concrete class
The Service class
The controller
View
Startup ConfigureServices
Object lifetimes
Singleton
Scoped
Transient
Instance
Object disposal
When to choose what?
Relationship and dependencies among lifetimes
Singleton depending on Scoped and Transient
Scoped depending on Singleton and Transient
Transient depending on Singleton and Scoped
Summary
Interception
Introducing Interception
The decorator
Patterns and principles for Interception
Benefits of the Decorator approach
Problems of the Decorator approach
Aspect-oriented programming
Cross-cutting concerns
Aspect
Aspect characteristics
Advantages
Aspect attached locations
Types of AOP
Investigating Interception
The Interception process
Castle Windsor
Demonstration for using the Castle Windsor
Creating an Interceptor
Attaching an Interceptor
Intermediate Language (IL) Weaving
IL Weaving process
Creating an aspect
Attaching the aspect
Interception in ASP.NET Core
Filters
Global filter
Attributes
Middleware
Registration
Execution
Ordering
Summary
Patterns - Dependency Injection
Dependency Inversion Principle
Problems
Solution
Inversion of Control (IoC)
Patterns
Constructor Injection pattern
The problem
The solution
Curveball
Injecting with .NET Core 2.0
Implementation inside ASP.NET Core 2.0
ControllerActivatorProvider.cs
Importance of the Constructor Injection pattern
Advantages of the Constructor Injection pattern
Disadvantages of the Constructor Injection pattern
Property Injection pattern
Curveball
Advantages of the Property Injection Pattern
Disadvantages of the Property Injection Pattern
Method Injection Pattern
Curveball
Injecting with .NET Core 2.0
Implementation inside .NET Core 2.0
MvcServiceCollectionExtensions.cs
Ambient context
Curveball
Implementation inside .NET Core 2.0
The advantages of the Ambient Context
The disadvantages of the Ambient Context
Summary
Anti-Patterns and Misconceptions on Dependency Injection
When does Dependency Injection become an anti-pattern?
Anti-patterns
Control Freak
Problem
Concrete Factory
Abstract Factory
Static Factory
Solution
Poor Man's DI
The approach
Problem
Solution
Bastard Injection
Problem
Solution
Constrained Construction
Problem
Solution
Service Locator
Design
Advantages
Problem
Code reusability
Solution
Refactoring steps
Summary
Dependency Injection in Other JavaScript Frameworks
TypeScript
Architectural changes
Modules in TypeScript
External modules
Dependency Injection in TypeScript
Angular
AngularJS
Examples using Visual Studio 2017
Understanding the structure of AngularJS bootstrap
Data access and Dependency Injection
Summing up Dependency Injection features inside AngularJS
Angular 2+
Microsoft's TypeScript is the preferred language in Angular 2+
Angular tools
Working with Angular
Editing the initial project
The structure of the main module
DI in Angular 4
The concept of a provider
Wrapping it up
Summary
Best Practices and Other Related Techniques
Tightly coupled systems
The problem
The solution - refactoring with DI
Interface extraction
Layered architecture
The problem - The concrete class reference again
Misuse of business and Data Access Layer assemblies
Best practice for layered architecture
Managed Extensibility Framework (MEF)
Layers and MEF implementation
Introduction of IUser
The IModuleRegistrar interface
The ModuleRegistrar class
The IModule interface
The ModuleInit class
The ModuleLoader class
Executing the ModuleLoader.LoaderContainer() method from Web App
What have we achieved with MEF?
Layers are separated
All classes inside layers are now internal
No concrete class instantiation inside the UI Layer
More layers can be added to the architecture
Conclusion
Summary
This book is an approach to the implementation of Dependency Injection techniques across the new .NET Core 2.0 version. The designers of .NET Core implemented plenty of functionalities related to good practices and have followed the principles stated by Robert C. Martin (the SOLID principles) in distinct areas of this version.
The purpose of this work is to go through those well-stated principles and identify and show through examples how they're implemented, and how they can be used by the programmer.
Chapter 1, The SOLID Principles of Software Design, introduces you to the five SOLID principles and how they are found or can be easily implemented in .NET Core 2.0.
Chapter 2, Dependency Injection and IoC Containers, gives you exposure to how Dependency Injection should be used either by itself or with the help of third-party containers.
Chapter 3, Introducing Dependency Injection in .NET Core 2.0, reviews the real implementation of DI inside .NET Core 2.0 from the point of view of Console applications.
Chapter 4, Dependency Injection in ASP.NET Core, provides a more detailed study of the implementation of DI techniques inside web applications that use ASP.NET Core 2.0, full of samples.
Chapter 5, Object Composition, takes you through all the hidden principles behind the concept of object composition and how it is applied in .NET Core 2.0 and ASP.NET Core MVC 2.0, forming a pillar of DI.
Chapter 6, Object Lifetime, the next DI pillar provides a deep dive into lifestyles maintained and typical management strategies, by the objects with DI in place, which enables better decision making with optimized configurations.
Chapter 7, Interception, the last pillar of DI ecosystem, provides techniques to intercept calls and insert code dynamically into the pipeline. This chapter also deals with interception's application in .NET Core 2.0 and ASP.NET Core 2.0 with proper illustrations.
Chapter 8, Patterns – Dependency Injection, walks you through the D of SOLID and all the important techniques to apply DI in applications with .NET Core 2.0.
Chapter 9, Anti-Patterns and Misconceptions on Dependency Injection, deals with the common bad usage of DI patterns and scenarios to avoid while coding, in order to get a good outcome from DI in the application.
Chapter 10, Dependency Injection in Other JavaScript Frameworks, teaches you about Dependency Injection techniques using other popular frameworks, such as Angular.
Chapter 11, Best Practices and Other Related Techniques, covers the well-proven coding, architectural, and refactoring practices that you should adopt while applying DI in your current and legacy applications.
You will need Visual Studio 2017 Community Edition, the Chrome Navigator, and IIS (Internet Information Server Express) to successfully test and execute all code files.
This book is for C# and .NET developers who have no idea what DI (Dependency Injection) is and would like to understand how to implement it in their applications.
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Dependency-Injection-in-.NET-Core-2.0. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/DependencyInjectioninNETCore20_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
This book focuses on techniques related to Dependency Injection and the way those techniques are implemented by default and can be extended by the programmer in .NET Core--the first version of .NET that executes on every platform.
It works on Windows, macOS, and Linux distro on the desktop, and the idea can even be extended to the mobile world covering the Apple, Android, and Tizen (Samsung) operating systems.
This is, with no doubt, the most ambitious project from Microsoft in its search for a universal coverage of programming technologies and tools, and it can be considered a natural step after the initial UWP (Universal Windows Platform) project that allows building applications for any device supporting Windows, from IoT devices to the desktop, XBOX, or HoloLens.
So, in this chapter we'll start with a quick review of the main architectural components of .NET Core and its derivative frameworks (such as ASP.NET Core), to be followed with the foundations on which Dependency Injection techniques are based, as part of the SOLID principles, stated by Robert C. Martin (Uncle Bob) in 2000. (See Wikipedia: https://en.wikipedia.org/wiki/SOLID_(object-oriented_design).)
Therefore, we'll revise those five SOLID principles, explaining their purpose and advantages, together with some basic implementations of each one of them in the C# language using Console applications coded in .NET Core. In all we'll see an explanation of each principle and its coverage:
Separation of concerns (clearly implemented in the core infrastructure of .NET Core and also from the initial configuration of pipelines and middleware in ASP.NET Core)
Open/Closed (already implemented in classic .NET Framework since version 3.0 and also present here)
Liskov Substitution Principle (available in two ways--in a classic manner through the support of typecasting, and through the use of generics)
Interface segregation: Explanation of Interface segregation and its advantages
Dependency Inversion: Explanation of the principle, its derivatives, and the concept of IoC containers
The evolution of programming techniques is, somehow, related to language evolution. Once the initial (and, in some ways, chaotic) times had passed, the universality of computing became clear, and the need for good patterns and languages capable of affording large projects turned out to be evident.
The 70s marked the start of the adoption of other paradigms, such as procedural programming, and later on, object-oriented programming (OOP), proposed by Ole-Johan Dahl and Kristen Nygaard with the Simula language, when they both worked at the Norwegian Computing Center. They were given the Turing Award for these achievements, among other recognitions.
A few years later (around 1979), Bjarne Stroustrup created C with Classes, the prototype of what C++ is today because he found valuable aspects in the Simula language, but he thought that it was too slow for practical purposes, being the first OOP language that was universally adopted.
C++ originally had imperative features and object-oriented and generic ones, while also providing the ability to program for low-level memory manipulation. While it's true that it has become a de facto standard for building critical systems and applications, for many people it was not adequate for LOB (Line of Business) applications.
Years later, Java and the .NET platforms proposed a much easier and affordable solution for many programmers while still moving within the ordered space that object-oriented programming languages promote.
So, OOP was adopted, and so far no other important programming paradigm has replaced these ideas. Certainly, there are other approaches, such as functional programming, but even the most significant representative of this tendency, JavaScript, is becoming more object-oriented in the latest versions (ECMAScript 2015).
.NET has been revamped lately in order to achieve the goal that Microsoft has pursued since Satya Nadella arrived in the company--"Any Developer, Any App, Any Platforms.".
According to Principal Manager Scott Hunter, the company now presents a set of unified application models that can be summarized in the following screenshot:
As you see, the situation now is quite promising for a .NET Developer. The screenshot shows a Common Infrastructure (compilers, languages, and runtime components), powered by Roselyn services and other features. All those integrate with the IDEs that support these projects, now including Visual Studio for Mac.
On top of that lies a .NET Standard Library, which has points in common that allow us to share code along the three different frameworks--the classic .NET Framework (in version 4.6.2, at the time of writing this), .NET Core (now in version 2.0), and Xamarin, which allows building applications for any type of mobile target--Android, iOS, Windows Phone, and Tizen (Samsung).
.NET Core is the new version of .NET presented officially in the summer of 2016, and updated to version 1.1 in the November Connect() event the same year. It's defined as a cross-platform, open source, cloud-ready and modular .NET platform for creating modern web apps, microservices, libraries, and console applications that run everywhere (Windows, Linux, and MacOS).
It can be deployed along with the application itself, minimizing installation issues.
Prior to its publication, Microsoft decided to restart the numbering, reinforcing the idea that this is a totally new concept with respect to classical versions, as a better way to avoid ambiguities.
MSDN architect Cesar de la Torre defines in his blog very precisely the goals and structure of .NET Core--unlike the traditional .NET Framework, which is a single package installation, system-wide, and Windows-only runtime environment, .NET Core is about decoupling .NET from Windows, allowing it to run in non-Windows environments without having to install a giant 400 Mb set of binaries (versus just the footprint of the components you need from .NET Core) plus the ability to deploy applications accompanying the framework itself, supporting side-by-side execution of different versions of the framework.
A very interesting part of its architecture and deployment infrastructure, as mentioned in the same source, is that instead of being part of the operating system, .NET Core is composed of NuGet packages and is either compiled directly into an application or put into a folder inside the application. This means applications can carry .NET Core within and thus are completely side by side on the machine.
I, personally, think this is absolutely crucial for the project to be successful. No side-effects, no component installation in the target machine, and no dependencies. (As you'll see throughout this book this avoiding of dependencies is totally foundational when building software that follows good practices.)
NET Core 2.0 - Supported OS Versions Proposal:
OS
Version
Architectures
Notes
Windows Client
7 SP1+
x64, x86
Windows Server
2008 R2 SP1+
x64, x86
Configurations: Full, Server Core, Nano
Windows IoT
10+
[C] arm32
IoT Core - see
Raspberry Pi instructions
Red Hat Enterprise Linux
7.3+
x64
This includes Centos and Oracle Linux
Fedora
25+
x64
Debian
8.7+
x64
Debian 9 (Stretch) workaround
Ubuntu
14.04+
x64, [C] arm32
This includes Linux Mint 17 for x64 For arm32, see
Raspberry Pi instructions
openSUSE
42.2+
x64
Tizen
4+
[S] arm32
Tizen .NET Developer Preview
Mac OS X
10.12+
x64
In Progress OS's
Arch Linux
[C] TBD
TBD
Blocked on
missing OpenSSL 1.0 package
in distro. Arch Linux community efforts tracked
here
.
FreeBSD & NetBSD
[C] TBD
TBD
Tracking
main issue
and
label
. NetBSD packages for
.NET Core 1.0.0
As for the types of programmable project available from any of the above-mentioned IDE's, .NET Core can support its own application model, and also the Universal Windows Platform Model, optionally compiled to .NET Native (see the following screenshot):
We end this introduction to .NET Core with the summary from the same page mentioned previously in relation to this framework:
Cross-platform
: .NET Core currently supports three main operating systems--Linux, Windows and OS X. There are other OS ports in progress such as FreeBSD, NetBSD, and Arch Linux. .NET Core libraries can run unmodified across supported OSes. The apps must be re-compiled per environment, given that apps use a native host. Users select the .NET Core supported environment that works best for their situation.
Open Source
: .NET Core is available on GitHub at
https://github.com/dotnet/core/blob/master/release-notes/2.0/2.0.0-preview1.md
, licensed with the MIT and Apache 2 licenses (licensing is per component). It also makes use of a significant set of open source industry dependencies (see release notes). Being OSS is critical for having a thriving community plus a must for many organizations where OSS is part of their development strategy.
Natural acquisition
: .NET Core is distributed as a set of NuGet packages that developers can pick and choose from. The runtime and base framework can be acquired from NuGet and OS-specific package managers, such as APT, Homebrew, and Yum. Docker images are available on docker hub. The higher-level framework libraries and the larger .NET library ecosystem are available on NuGet.
Modular framework
: .NET Core is built with a modular design, enabling applications to include only the .NET Core libraries and dependencies that are needed. Each application makes its own .NET Core versioning choices, avoiding conflicts with shared components. This approach aligns with the trend of developing software using container technologies such as Docker.
Smaller deployment footprint
: Even when in v1.0/1.1 the size of .NET Core is a lot smaller than .NET Framework; note that the overall size of .NET Core doesn't set out to be smaller than the .NET Framework over time, but since it is pay-for-play, most applications that utilize only parts of CoreFX will have a smaller deployment footprint.
Fast release cycles of .NET Core
: .NET Core's modular architecture plus its OSS nature provide more modern and much faster release cycles (even per NuGet package) compared to slow release cycles from larger monolithic frameworks. This approach allows a much faster innovation pace from Microsoft and the OSS .NET community than what was traditionally possible with the .NET Framework.
Thus, there are multiple application model stacks built on top of the .NET Core that allow developers to build applications ranging from console applications, across UWP Windows 10 apps (PC, tablet, and phones) to scalable web applications and microservices with ASP.NET Core.
ASP.NET applications that use .NET Core promote a model based on the previous MVC model, although built from scratch, targeted at cross-platform execution, the elimination of some unnecessary features, and the unification of the previous MVC with the web API variant; so, they work with the same controller type.
Besides this, the code doesn't need to be compiled prior to execution while you're developing. The BrowserSync technology allows you change the code on-the-fly and the Roselyn services take care of updating; so, you just have to refresh your page to see the changes.
ASP.NET Core also uses a new hosting model, completely decoupled from the web server environment that hosts the application. It supports IIS versions and also self-hosting contexts via Kestrel (cross-platform, extremely optimized, built on top of LibUv, the same component that Node.js uses) and WebListener HTTP (Windows-only) servers.
As part of its architecture, it proposes a new generation of middleware that is asynchronous, very modular, lightweight, and totally configurable, where we define things such as routing, authentication, static files, diagnostics, error handling, session, CORS, localization; and they can even be user-defined.
Notice also that ASP.NET Core can run as well in the classic .NET Framework with access to the functionality exposed by those libraries. The following screenshot shows the schema:
ASP.NET Core joins many things that were separate in previous versions. Thus, there are no distinctions between MVC and Web API and, if you target .NET Core or if you prefer to target any of the other version of .NET, the architectural model can be MVC using this rebuilt architecture.
In addition, a new built-in IoC container for dependency injection is responsible for bootstrapping the system, together with a new configuration protocol, which we'll see in practice in the following chapters.
Since this book deals with .NET Core and ASP.NET Core and their built-in capabilities covering SOLID principles in general and DI in particular, we're using the latest available version of Visual Studio (Visual Studio 2017 Enterprise), which includes full support for these platforms, together with a bunch of convenient extensions and templates.
You can also use Visual Studio 2017 Community Edition, which is free, or any higher version with practically no changes, as far as the codes samples are concerned.
If you're a Mac user, you can also use Visual Studio for Mac (https://www.visualstudio.com/vs/visual-studio-mac/), available since November 2016, and, if you prefer a light, full-fledged, and free IDE for any platform (Linux, Mac or Windows), you can opt for Visual Studio Code (https://code.visualstudio.com/download), which also has excellent editing and debugging capabilities. All of them have full support for .NET Core/ASP.NET Core as well (see the following screenshot):
Throughout this and other chapters, I'll use indiscriminately .NET Core or ASP.NET Core for the demos, depending on whether we need a more complex user interface or not. Notice also that .NET Core (for the time being) does not offer any visual UI beyond Console applications.
Actually, the currently available templates shown by default when we select New Project and click on .NET Core are the ones you can see in the following screenshot:
As you see, the choices are basically threefold (besides testing): Console apps, Class libraries, and ASP.NET Core Web apps, based on NET Core. In the three cases, the resulting apps run on any platform.
It's important to keep in mind that, with NET Core, you no longer depend on .NET Framework libraries (the BCL libraries), either installed by the OS or manually and located in the GAC (Global Assembly Cache).
All libraries are available via NuGet and downloaded accordingly. But, if you have tried .NET Core prior to Visual Studio 2017, you might miss the file project.json in which all dependencies were referenced.
The official documentation states that when using Visual Studio 2017:
MSBuild supports .NET Core projects, using a simplified
csproj
project format that makes it easier to be edited by hand, without the need for unloading the project
There is support for file wildcards in the project file, enabling folder-based projects that don't require individual files to be included
NuGet package references are now part of the
csproj
format, consolidating all project references in one file
So, if you try a new .NET Core project with this tool, the project's dependencies are now referenced in the csproj file (in XML format), as you can see when opening it in any text editor:
In parallel, Visual Studio reads that file, creates a Dependencies entry in the Solution Explorer, and starts looking for that information (either in the PC's cache or in NuGet).
Note also that they're not real, classic DLLs, but fragments of code that are assembled all together at compile time to minimize size and launch time. If you take a look at that entry you can see the Dependencies' dependencies, and so on:
Another critical point to highlight relates to the deliverables produced after the compiling process. If you open the demo included as ConsoleApp1 (or create a basic one of your own), and just compile it, you'll see that the bin directory does not contain any executable file. You'll see a DLL with that name instead (ConsoleApp1.dll).
When you launch the application (after adding a Console.Read() sentence to stop execution), you'll see that the executable is, indeed, dotnet.exe. And the same is true when you open the Diagnostics Tool and take a snapshot of the executable to see what is in place in that moment. The following screenshot shows the situation:
The reason for this is directly related to the complexity of this model. The application is thought to execute on distinct platforms. The default option allows the deployment architecture to determine the best way to configure the JIT compilers depending on the target. This is why the execution is undertaken by the dotnet runtime (named dotnet.exe).
From the point of view of deployment, in .NET Core, two types of application are defined: portable and self-contained.
In .NET Core, portable applications are the default. Of course, that means that (as developers) we can be sure about their portability in distinct .NET core installations. However, a standalone app does not depend on any previous installation to run. That is to say, it holds within itself all the necessary components and dependencies, including the runtime packaged with the application. Certainly, that builds a larger app, but it also makes the application capable of executing on any .NET Core platform whether you have .NET Core installed in the target or not.
For the main purposes of this book, it doesn't matter which runtime mode we choose. Anyhow, this brief introduction can give you an idea of how the new framework behaves and is managed inside Visual Studio 2017.
And, remember, anything I do using Visual Studio 2017, you can also do with Visual Studio Code.
Some programming guidelines have a comprehensive, general-purpose intention, while others are mainly designed to fix certain specific problems. Therefore, before we focus on specific problems, it's important to review those features that can be applied in different scenarios and solutions. I mean those principles that you should consider beyond the type of solution or specific platform to program for.
This is where the SOLID principles (and other related problems) come into play. In 2001, Robert Martin published a foundational article on the subject (http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod), in which he enumerated a set of principles and guidelines that, in his own words, focus very tightly on dependency management, its potential problems, and how to avoid them.
To explain this further, in his words, poor dependency management leads to code that is hard to change, fragile, and non-reusable. So, this principle is directly related with two of the OOP mantras--reusability, and maintainability (the capacity to change as the project grows, one of the main goals of inheritance).
Overall, Martin stated his 11 commandments to consider, but they can be divided into three areas:
The five SOLID principles, which deal with class design
The other six principles, mainly focused on packages--three of them are about package cohesion, and the other three explain the dangers of package coupling and how to evaluate a package structure
We're going to start with the SOLID principles, which by extension not only affect the class design, but also other aspects of software architecture.
This applies to other popular frameworks as well, such as AngularJS (and even more in Angular 2), both designed not only with the Single Responsibility principle in mind but also based on the Dependency Inversion principle (the D in SOLID).
The following diagram schematizes the five principles' initials and correspondences:
The explanation of every letter in the acronym as expressed in Wikipedia is as follows:
S - Single Responsibility Principle
: A class should have only a single responsibility (that is, only one potential change in the software's specification should be able to affect the specification of the class). Martin states that this principle is based on the principle of cohesion, previously defined by Tom de Marco in a book named
Structured Analysis and Systems Specification
and by Meilir Page-Jones in his work
The Practical Guide to Structured Systems Design
.
O - Open/Closed Principle
: Software entities should be open for extension, but closed for modification. Bertrand Meyer was the first to propose this principle. Martin puts this in another way at
http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
, saying that
You should be able to extend a class's behavior, without modifying it.
L - Liskov Substitution principle
: Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. Barbara Liskov first stated this, and Martin rephrases the principle in this manner--
Derived classes must be substitutable for their base classes
.
I - Interface Segregation principle
:
Many client-specific interfaces are better than one general-purpose interface
. Robert C. Martin was the first to use and formulate this principle, which he rewords in the aforementioned article as--
Make fine grained interfaces that are client specific.
D - Dependency inversion principle
:
We should 'Depend on Abstractions'. Do not depend upon concretions
. This too is an idea developed by Robert C. Martin.
The Single Responsibility Principle (SRP), focuses on the fact that there should never be more than one reason for a class to change. In this context, responsibility is defined as a reason for a change. If, under any circumstances, more than one reason comes up to change the class, then the class' responsibilities are multiple and should be redefined.
This is, indeed, one of the most difficult principles to apply properly because as Martin says, conjoining responsibilities is something that we do naturally. In his book, Agile Principles, Patterns, and Practices in C#, Martin proposes a canonical example to show the differences, as follows:
interface Modem { public void dial(String phoneNumber); public void hangup(); public void send(char c); public char recv(); }
Given the previous interface, any class implementing it has two responsibilities: connection management and the communication itself. Such responsibilities can be used from the different parts of an application, which, in turn, might change as well.
We're going to use the Visual Studio 2017 Class Designer to express the way Martin proposes we express this class design instead:
As we see, in Martin's solution, the class depends on two interfaces, each one in charge of a responsibility--connection and channel transmission (two abstractions, really: remember that an interface is not compiled and it only serves as a contract for the compiler to check).
However, one wonders, should these two responsibilities be separated? It only depends on application changes. To be precise, the key here is to know whether changes in the application affect the signature of connection functions. If they do, we should separate both; otherwise, there's no need for separation because we would then create needless complexity.
So, overall, a reason to change is the key, but keep in mind that a reason to change is applicable only if changes occur.
In other situations, there might be reasons to keep distinct responsibilities together as long as they are closely related to the business definitions or have to do with the hardware requirements of the operating system.
As always happens, there were previous approaches to the problem of software separation. Dijkstra in "On the role of scientific thought" (http://www.cs.utexas.edu/users/EWD/transcriptions/EWD04xx/EWD447.html) mentioned that It is what I sometimes have called "the separation of concerns", which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts, that I know of.
Another advance was Information Hiding, defined by Wikipedia (https://en.wikipedia.org/wiki/Information_hiding) as the principle of segregation of the design decisions in a computer program thataremost likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed. This was the seed that later became a basic pillar of OOP--Data Encapsulation.
Even Barbara Liskov, whom we mentioned in connection with the substitution principle, published at the same time Programming With Abstract Data Types (http://dl.acm.org/citation.cfm?id=807045), which she describes as an approach to the computer representation of abstraction. The definition of ADTs as a class of objects whose logical behavior is defined by a set of values and a set of operations links data and functionality.
Later approaches have improved these ideas. Proposals for Code Contracts, originally introduced by Bertrand Meyer in his Eiffel language, and implemented in C# via Code Contracts (https://msdn.microsoft.com/es-es/library/dd264808(v=vs.110).aspx) foster the use of pre and post conditions that our software has to accomplish.
Finally, we can think of the separation of what Hayim Makabee (https://effectivesoftwaredesign.com/2012/02/05/separation-of-concerns/) reports as cross-cutting concerns--aspects that might affect distinct pieces of software in even distinct layers of the application and that should be managed in a similar fashion (authorization or instrumentation issues, and so on.). In .Net, we count on Attributes, applicable equally to classes and class members, to modify and tune such behavior.
A bit later in the same article, Makabee clearly establishes the main purposes for these techniques. If we understand coupling as the degree of dependency between two modules, the goal is to obtain low coupling. Another term is cohesion or the measure of how strongly-related the set of functions performed by a module is. Obviously, high cohesion is better.
He ends by summarizing the benefits obtained with these techniques:
Patterns and methodologies are always intended to reduce coupling and at the same time increase congruity. By hiding information, we reduce coupling since we isolate implementation details. Thus, ADT's reduce coupling by using clear and abstract interfaces. We have an ADT specifying the set of function that can be executed on a type, that's more cohesive than a global data structure modified by external functions. The way that OOP reaches that cohesion is the implementation of two of its basic principles--encapsulation and polymorphism, together with dynamic binding. Furthermore, inheritance reinforces cohesion by means of hierarchies that are based on generalization and specialization, which permits a suitable separation from the functionality belonging to a superclass from its subclasses. AOP, in turn, supplies solutions for cross-cutting concerns in a way that both aspects and functionality may become more cohesive.
Maintainability, reusability, and extensibility are only three of the main advantages gained with its implementation.
All of us have gone through cases and scenarios where the separation of concerns lies at the heart of the system or technology that implements it. One such case is HTML (and, especially HTML5).
Since its inception, the standard HTML5 was thought to clearly separate content from presentation. And the popularity of mobile devices only made that requirement more evident. The huge variety of form factors available today demanded a technology capable of adapting to these sizes, in such a way that content could be held by HTML tags and the final presentation in a given device decided at runtime depending on the device.
Therefore, some tags were declared deprecated, such as <font>, <big>, <center>, and a list of others, and the same happened to some attributes, such as background, align, bgcolor, or border since they didn't make sense in this new system. Even some of them that still remain unchanged and that have a visual effect on the output (such as <b>, <i>, or <small>) are kept for their semantic meaning and not for their presentational effects, which is a role totally dependent on CSS3.
