Common Language Runtime (CLR)

The .Net framework supports C#, Visual Basic, and Visual C++.

All supported languages are compiled to the IL (Intermediate Language) used by .Net. When an application is run, the IL (Intermediate Language) will be compiled to local machine code as needed.

Because the IL (Intermediate Language) is not compiled to machine-specific code until the application is run, .Net executables and libraries can be shared between computers without concern for what OS they are running. This also allows you to use several different supported languages within one application.

Even Linux is supported, through the Mono libraries.

Managed Vs Un-Managed Code

Managed code is compiled to the IL (Intermediate Language) and is run by the CLR (Common Language Runtime). It is interoperable on different systems.

Un-Managed code is compiled straight to the local machine code, so it will only run on machines with the same OS version. This code will not be run by the CLR (Common Language Runtime) so it will not have the benefits of the CLR services.

The execution process for managed code is:
    Choose a language compiler
    Compile to the IL (Intermediate Language)
    Compile from IL to machine code (this occurs when the code is executed)
    Execute the machine code

CLR Services

The Common Language Runtime provides: garbage collection, type checking, exception handling, etc.

Garbage Collection

Garbage collection is the automatic process of checking heap memory for objects that are not longer being referenced by any process. This memory is freed up for future use.

Assembly Vs Namespace

An assembly is collection of files compiled into a DLL (library) or EXE (executable program).

A namespace is a logical organization created by the programmer. It can span across assemblies, and an assembly can contain multiple namespaces.

Assembly

An assembly is an EXE or a DLL.
An assembly is the smallest unit of deployment.
An assembly is a collection of types and resources.

Private Assembly

A private assebly can only be used by the application is was deployed with. It must be located in the application's home folder or one of its subdirectories.

A private assembly must be designed for side-by-side work with other versions of itself. It must be accompanied by an assembly manifest to make this possible.

Shared Assembly

A shared assembly can be used by multiple applications. It will be loaded into the Global Assembly Cache. These assemblies are only loaded into memory if they are required.

A shared assembly must be strong-named, ie. have a unique id to prevent assembly conflicts.

Dynamic Assembly

An assembly created by an application as it runs.

Satellite Assembly

A satellite assembly is a DLL containing localization resources specific to a given culture. They are only loaded if an application needs that culture's information (language or images).

These assemblies do not contain code (beyond what is auto-generated). They contain text, images, etc. Just resources.

These assemblies are not in the main assembly of an application, so that they can be changed without requiring a re-compilation of the entire application.

Find Assembly In GAC

Windows hack to find the location of an assembly in the GAC:
1. Run > C:\\Windows\assembly\gac_msil
2. Find the assembly in the list, select it to see the location in the address bar

Assembly Strong Name

This is a unique id made up of:
    the assembly name
    the version number
    optional cultural information
    a digital signature
    and a public key
    
The public key corresponds to the private key the used for the digital signature.

Assemblies with the same Strong Name should be identical.

Assembly Manifest

The assembly manifest is an XML file containing the names and hashes of all files in the assembly, and a reference list of all external dependencies.

Multi-Targeted Library

Duplicate Project File

Create a *.csproj for each target framework and compile each one separately.

Must keep any changes to these files in sync.

Build Configurations

Add a build configuration to the project for each target framework.

Makes project files more complex and error-prone.

Visual Studio 2017

[Bugsnag: How To]

1) Open *.csproj
2) Find the "<TargetFramework>" tag
3) Change it to "<TargetFrameworks>"
4) Update the value to a semi-colon (;) delimited list of all the frameworks you want to target

Example

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <PackageId>MyProject</PackageId>
    <Title>My Project Title</Title>
    <TargetFrameworks>net35;net40;net45;netstandard1.3;netstandard2.0</TargetFrameworks>
  </PropertyGroup>
</Project>

Haven't gotten this to work yet.
All the examples have "<Project Sdk="Microsoft.NET.Sdk">", so this may not work for "<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">".

MSBuild will automatically compile your project for each framework listed.
It will produce one *.dll for each target framework.

You're supposed to be able to target multiple frameworks in a Test project the same way, so you can auto-test all those different frameworks, but reading about it, it sounds buggy still.

GAC

GAC: Global Assembly Cache

View list of cached assemblies:
1) Open 'Developer Command Prompt'
2) run 'gacutil -l'

View filtered list of cached assemblies:
1) Open 'Developer Command Prompt'
2) run 'gacutil -l | findstr "search string"'

Unit Testing

Add A Unit Test Project

To add a unit test project to your solution in Visual Studio:
File menu > New Project > Installed > Visual C# > Test > Unit Test Project

This project will have a reference to assembly Microsoft.VisualStudio.QualityTools.UnitTestFramework.

Your unit test project will also need to reference the project(s) you are testing.

Unit Test File

Each unit test file needs to include:


using Microsoft.VisualStudio.TestTools.UnitTesting;

Unit Test Class

Each test class must be public, and have attribute TestClass. Each test method must be public, return void, have no parameters, and have attribute TestMethod.


using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MyTests
{
    [TestClass]
    public StudentTests
    {
        [TestMethod]
        public void Student_AddClass_Success()
        {
            //test code
        }
    }
}

Running Unit Tests

In Visual Studio, build the unit test project. Test menu > Windows > Test Explorer. You can run tests from here.

To run tests with breakpoints, place your breakpoints. Test menu > Debug > Selected Tests or All Tests.

Command Prompt

To run tests by TestCategory:
    - open Visual Studio > Developer Command Prompt
    - cd to location of unit test container (the unit test's dll)

Vstest.Console.exe myTests.dll /TestCaseFilter:TestCategory=Nightly
or

mstest /testcontainer:myTests.dll /category:"Nightly" /resultsfile:locationToSaveTo.txt

You can use AND or OR to specify multiple categories, but you cannot mix them or nest them.

Unit Test Standards

Formal Language

Test Doubles: pretend objects used during testing. Informally called "Mocks".

    Dummy:
        A required parameter.
        You don't care how it is used, or (ideally) it won't be used at all.
    
    Stub:
        Intended to be used, and always returns the same value.
        The intention is to decouple a whole subsystem from the current tests.
    
    Spy:
        A stub that also tracks how it used, how many times it is called, etc.
        This more tightly couples your test to a particular implementation of the system.
    
    Mock (aka True Mock):
        A spy that also contains verification code to check that the object is used in the expected way.
        This becomes part of your test case.
        Mocking frameworks create these types of Test Doubles.
    
Fake (its own category):
    Implements real business logic.
    Behaves differently with different data.
    May become so complicated, it requires tests of its own.
    Ex: an in-memory database - it has behavior but takes shortcuts that are not viable in production.

Styles

State Verification: checking object and system state after the test. Uses Stubs and Spies.

Behavior Verification: checking that the correct methods were called. Uses Mocks.
    
Method Names

There are several standards for naming methods. This is my preference.

NameOfMethodTested_SetupDescription_ExpectedResult()

Method Body

Use the arrange, act, assert sections and labels.


public void NameOfMethodTested_SetupDescription_ExpectedResult()
{
    //arrange
    //put all the setup, like object instantiation, here
    
    //act
    //call the method you are testing
    
    //assert
    //validate the results
}

Unit Test Assertions

Assert

Some standard asserts:


Assert.AreEqual(x, y);
Assert.IsTrue(x);
Assert.IsFalse(y);
Assert.IsNull(x);
Assert.IsNotNull(y);

Expected Exception

To verify that an expected exception was thrown, add the ExpectedException attribute to the test method instead of asserting anything.

You can use any exception type here. It is recommended that methods throw specific exceptions, so test for the most specific applicable exception.

You cannot test for more than one exception type at a time.


[ExpectedException(typeof(ArgumentNullException))]
public void Student_AddNullGrade_ArgumentNullException()
{
    //arrange
    Student student = new Student();
    
    //act
    student.AddGrade("English", null);
    
    //assert exception
}

Unit Test Annotations

Required annotations

[TestClass]
public class MyTests
{
    [TestMethod]
    public void TestA()
    {
    }
}

Optional annotations:
    [AssemblyInitialize] runs once before the TestMethods in this assembly
    [AssemblyCleanup] runs once after the TestMethods in this assembly
    [ClassInitialize] runs once before the TestMethods in this class
    [ClassCleanup] runs once after the TestMethods in this class
    [TestInitialize] runs before each TestMethod
    [TestCleanup] runs after each TestMethod

Execution Order:
    AssemblyInitialize
    ClassInitialize
    TestInitialize
    TestMethod
    TestCleanup
    ClassCleanup
    AssemblyCleanup

Annotations used in Test Explorer window to select groups of tests
    - right-click in window > Group By > Traits

[TestCategory("Nightly")]
[TestCategory("ShoppingCart"), TestCategory("Weekly")]

Annotations for use by team, not used by framework

[Owner("JSmith")] //dev responsible for maintenance of test
[Priority(2)]

Moq

Moq is a framework for mocking objects to facilitate unit testing. Eg, you can mock a database connection to isolate the behavior of the method you are testing from any actual database.

Moq mocks objects by deriving from them and overriding their properties and methods. Therefore, all properties and methods you want to mock must be declared virtual. Interfaces are easy because their properties and methods are inherently virtual. You cannot mock a static method.

Some of these instructions assume you are using Visual Studio.

Installation

Tools menu > Library Package Manager > Package Manager Console.
Verify the Default Project is your unit test project.
Verify Package Source is "nuget.org".
Run "Install-Package Moq"

In each unit test file, add Moq.


using Moq;

Basic Example

In this example, MethodBeingTested will call mockInterface.MethodA. It will receive returnValue.


Mock<MyInterface> mockInterface = new Mock<MyInterface>();
mockInterface.Setup(x => x.MethodA()).Returns(returnValue);
MethodBeingTested(a, b, mockInterface.Object);

Or you can create a moq factory.

MockRepository mockRepository = new MockRepository(MockBehavior.Loose) { DefaultValue = Default.Mock };
Mock<MyInterface> mockInterface = mockRepository.Create<MyInterface>();

Mixing Call Types

Mock one method on an object, and use the real call on another.


Mock<MyObject> obj = new Mock<MyObject>() { CallBase = true };
//Setup the mocked method
//all methods not explicitly Setup will use the real call instead

Methods With Parameters

When the parameter value does not matter.

mockInterface.Setup(x => x.MethodB(It.IsAny<int>(), It.IsAny<string>())).Returns(returnValue);

When with parameter value is specific.

mockInterface.Setup(x => x.MethodB(5, It.IsAny<string>())).Returns(returnValue);

Return

To return a null, you must specify a null of the expected object type.

mockInterface.Setup(x => x.MethodA()).Returns(default(Object));

You can return a sequence of different values, as of Mock 4.2.1312.1622.

//first time Method is called, resultA is returned
//each time after that, resultB is returned
mockObj.SetupSequence(x => x.Method()).Returns(resultA).Returns(resultB);

Properties


mockInterface.Setup(x => x.Property).Returns(returnValue);

Verify

Verify that a mocked method was called, and how many times it was called.

mockInterface.Verify(x => x.MethodA(), Times.Once());

Times: AtLeast, AtMost, AtMostOnce, Between, Exactly, Never, Once.

Verify that a mocked property was got.

mockInterface.VerifyGet(x => x.Property);
Memory-Mapped Files

Enables separate processes on the same machine to share data files.

Side-by-Side Execution

Allows multiple versions of an application to run at the same time on the same machine.

Dispose Vs Finalize

Both methods perform garbage collection on an object on the heap.
Finalize() is called by the CLR (Common Language Runtime) only.
Dispose() can be called explicitly in the programmer's code.

Covariance And Contravariance

(New in C# 4.0)

Covariance Or "out"

Casting a generic type to its base type.
Ex: cast IEnumerable<string> to IEnumerable<Object>

Contravariance Or "in"

Casting a generic type to a derived type.
Ex: cast IComparer<Object> to IComparer<string>

Localization And Globalization

Globalization

Making an application ready for localization, by separating user-facing text and images from the application code. These resources are placed in a separate assembly.

Making an application culture-neutral and language-neutral, and supporting localized user interfaces and regional data.

Localization

Customizing an application for specific cultures/regions by creating different satellite assemblies with the applications resources (text and images) translated variously.

Resources such as error messages, dialog boxes, menus, and so on.
Plugin Architecture

Visual Studio and Minecraft are both examples of plugin architectures. The core functionality remains the same, but they both allow massive additions of functionality through plugins without recompiling the core code.

Closed to alteration, open to extension.

The key is that all dependencies point from plugin to core program, never the reverse.

Use case example: basic website product with myriad optional features that can be added a la carte. The features can be deployed in separate locations for each client, or as a multi-tenant application where features are loaded based on the user.

MEF

MEF stands for Managed Extensibility Framework. It was integrated into .Net in 4.0.

MEF allows an application to be extended through a set of components that may be imported or exported.
1) Create an ASP.Net MVC 4 application
2) install Nuget package MEF.MVC4
(instructions continued at https://visualstudiomagazine.com/articles/2014/03/14/asp-dotnet-extensibility-with-mef.aspx)


Compiler Optimizations

The Common Language Runtime (CLR) uses a Just In Time (JIT) compiler to compile each method in the Common Intermediate Language (CIL) into native code, and then runs the native code.

Some compiler optimizations are made when the C# code is compiled into the Intermediate Language. Some are made when the IL is compiled into native code.

Constant Folding

Computing constants at compile time.


//original
int i = 320 * 220 * 49;

//optimized
int i = 3449600;


//original
int i = x * 0;

//optimized
int i = 0;


//original
string s = "abc" + "def";

//optimized
string s = "abcdef";

Constant Propagation

Replacing constant variables with their values. Constant propagation and folding are used alternately until no more changes can be made.


//original
int x = 14;
return y + (x/2);

//optimized
return y + 7;

Common Subexpression Elimination


//original
a = b * c + g;
d = b * c * e;

//optimized
temp = b * c;
a = temp + g;
d = temp * e;

Dead Code Elimination

Removing code that does not affect the program result. Include unreachable code and code that only affects dead variables.


//original
int a = Method();
int b = 7;
return a + 3;
b = 24;
return 0;

//optimized
int a = Method();
return a + 3;

Loop Invariant Motions

Code withing a loop that can be moved outside the loop without changing the result is moved.

Loop Unrolling

Small loops with small bodies are "unrolled" into their linear steps.

Method Inlining

Aka Inline Expansion. Replaces a method call with the full body of the method.

May result in a small performance gain due to avoiding Function Call Overhead.
May also cause a large memory penalty, like if a 10-line method is inlined in 10 locations, resulting in longer code.

The .Net rule of thumb is methods < 32 bytes long, with no complex branching logic and no exception handling, may be inlined. The compiler errs on the side of not inlining methods.

Register Allocation

Deciding which of your variables will first be allocation to the few available registers.
Customize Build

If you make changes to the *.csproj file, or any file it imports, you'll need to unload and reload the project from Visual Studio for the changes to be picked up.

Display Message

Very simple example of extending the Visual Studio build process.
1) Open the *.csproj file for your project.
2) Scroll to the bottom where the "Target" tags are commented out.
3) Uncomment the "AfterBuild" Target tag and add a Message to it:

    <Target Name="AfterBuild">
        <Message Importance="High" Text="Test after build"/>
    </Target>
The "Importance" is set to "High" so the message is certain to be shown.
4) Build the project normally and see the message in the Output Window.

Targets

Targets group tasks together in order and allow the build process to be factored into smaller units.

To run a target as part of your build process, import it into your *.csproj file.
See the default import as an example:

    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

You can create your own target files:

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <Target Name="PrintFromTarget" BeforeTargets="Build">
            <Message Importance="High" Text="Printing from imported target"/>
        </Target>
    </Project>
Save the target text file "test.targets" in the same directory as the *.csproj file.

The target "Name" can be set to anything. If two targets have the same Name, the last one defined will overwrite the earlier one.
Do not use the standard Names "BeforeBuild" or "AfterBuild".

A target will only be run once per build.

Use the "BeforeTargets" and "AfterTargets" attributes to specify when during the build this target should be run.

When specifying a directory path, use variables like these:
Project="$(SolutionDir)\test.targets"
Project="$(ProjectDir)\test.targets"
Include="$(TargetDir)$(TargetName).txt"
[These are called Macros.]

If you edit a *.targets file, you will need to manually unload and reload the project in Visual Studio for the changes to be loaded.
Use "Rebuild" instead of "Build" when testing targets.

Incremental Build

MSBuild will compare the timestamps of input and output files for a build/target command, and decide whether the command needs to be run.
This speeds up builds by not redoing already completed work.

To enable this in custom targets, you must have a one-to-one mapping between input and output files.

Exec Command

To run a console command as part of the build:

<Target Name="Test" AfterTargets="AfterBuild">
    <Exec Command="Path\Test.exe" IgnoreExitCode="True"/>
</Target>
The "Test.exe" will be run.
Any error codes from the exe will be ignored. If "IgnoreExitCode" were not specified, then an error in the exe would stop the build.

To display the error from an Exec in the Output Window":

<Exec Command="Path\Test.exe" IgnoreExitCode="True" ConsoleToMSBuild="True">
    <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
</Exec>
<Message Importance="High" Text="$(OutputOfExec)"/>

To capture the exit code and only show the message if an error occurred:

<Exec Command="Path\Test.exe" IgnoreExitCode="True" ConsoleToMSBuild="True">
    <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
    <Output TaskParameter="ExitCode" ItemName="ExitCodes"/>
</Exec>
<Message Importance="High" Text="$(OutputOfExec)" Condition="'%(ExitCodes.identity)'!=0"/>

Tasks

You can compile .Net classes that implement the ITask interface (in the Microsoft.Build.Framework library).
These operations can be called from MSBuild Tasks.

Either implement the ITask interface entirely, or derive from the Task class and override the functionality you need.
The method Execute is required. This is what is run by MSBuild.
Execute accepts no parameters and returns True if the task succeeds.


using System;  
using Microsoft.Build.Framework;  
using Microsoft.Build.Utilities;  
  
namespace MyTasks  
{  
    public class SimpleTask : Task  
    {  
        public override bool Execute()  
        {  
            return true;  
        }  
    }  
}  


<UsingTask TaskName="SimpleTask" AssemblyName="MyTasks"/>
<Target Name="MyTarget">  
    <SimpleTask />
</Target>  

Instead of passing parameters to Execute, you can add Properties to the Task which will be set by MSBuild just before the Task is run.


using System;  
using Microsoft.Build.Framework;  
using Microsoft.Build.Utilities;  
  
namespace MyTasks  
{  
    public class SimpleTask : Task  
    {  
        public string MyProperty { get; set; }
        public override bool Execute()  
        {  
            return true;  
        }  
    }  
}  


<UsingTask TaskName="SimpleTask" AssemblyName="MyTasks"/>  
<Target Name="MyTarget">  
    <SimpleTask MyProperty="SomeValue" />  
</Target>  

If you add the "[Required]" attribute to a Task property, the build will fail if the property is not set in the project or target file.

Specifying "AssemblyName" has not worked for me, using "AssemblyFile" instead:

<UsingTask TaskName="SimpleTask" AssemblyName="$(ProjectDir)$(OutputDir)MyTasks.dll"/>  
Assuming the dll is included in the project.
If referencing a "ref" dll added by NuGet, make the path relative to $(SolutionDir).

Errors in the task will stop the build. To ignore errors:

    <SimpleTask MyProperty="SomeValue" ContinueOnError="True" />  

To return output from a Task, mark the property as Output:

        [Output]
        public string MyProperty { get; set; }
And capture the output in the target:

    <SimpleTask MyProperty="SomeValue">
        <Output TaskParameter="MyProperty" PropertyName="LocalName"/>
    </SimpleTask>

Aliases

You can alias a referenced library from within the *.csproj file.

    <Reference Include="WithoutHaste.DataFiles, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\WithoutHaste.DataFiles.1.0.0\lib\net20\WithoutHaste.DataFiles.dll</HintPath>
      <Private>True</Private>
      <Aliases>EarlyDocs_WithoutHaste_DataFiles</Aliases>
    </Reference>
This occurs before "using alias = namespace;" in the code.

You cannot use periods (.) in the alias.

Seems to be ignored by command line msbuild, which has no alternative method.

MSBuild Macros

$(Configuration) The name of the current project configuration, for example, "Debug".

$(DevEnvDir) The installation directory of Visual Studio (defined as drive + path); includes the trailing backslash '\'.

$(FrameworkDir) The directory into which the .NET Framework was installed.

$(FrameworkSDKDir) The directory into which you installed the .NET Framework. The .NET Framework could have been installed as part of Visual Studio or separately.

$(FrameworkVersion) The version of the .NET Framework used by Visual Studio. Combined with $(FrameworkDir), the full path to the version of the .NET Framework use by Visual Studio.

$(FxCopDir) The path to the fxcop.cmd file. The fxcop.cmd file is not installed with all Visual C++ editions.

$(IntDir) Path to the directory specified for intermediate files. If this is a relative path, intermediate files go to this path appended to the project directory. This path should have a trailing slash. This resolves to the value for the Intermediate Directory property. Do not use $(OutDir) to define this property.

$(NuGetPackageRoot) Path to NuGet packages.

$(OutDir) Path to the output file directory. If this is a relative path, output files go to this path appended to the project directory. This path should have a trailing slash. This resolves to the value for the Output Directory property. Do not use $(IntDir) to define this property.

$(Platform) The name of current project platform, for example, "Win32".

$(ProjectDir) The directory of the project (defined as drive + path); includes the trailing backslash '\'.

$(ProjectExt) The file extension of the project. It includes the '.' before the file extension.

$(ProjectFileName) The file name of the project (defined as base name + file extension).

$(ProjectName) The base name of the project.

$(ProjectPath) The absolute path name of the project (defined as drive + path + base name + file extension).

$(RemoteMachine) Set to the value of the Remote Machine property on the Debug property page. See Changing Project Settings for a C/C++ Debug Configuration for more information.

$(RootNameSpace) The namespace, if any, containing the application.

$(SolutionDir) The directory of the solution (defined as drive + path); includes the trailing backslash '\'. Defined only when building a solution in the IDE.

$(SolutionExt) The file extension of the solution. It includes the '.' before the file extension. Defined only when building a solution in the IDE.

$(SolutionFileName) The file name of the solution (defined as base name + file extension). Defined only when building a solution in the IDE.

$(SolutionName) The base name of the solution. Defined only when building a solution in the IDE.

$(SolutionPath) The absolute path name of the solution (defined as drive + path + base name + file extension). Defined only when building a solution in the IDE.

$(TargetDir) The directory of the primary output file for the build (defined as drive + path); includes the trailing backslash '\'.

$(TargetExt) The file extension of the primary output file for the build. It includes the '.' before the file extension.

$(TargetFileName) The file name of the primary output file for the build (defined as base name + file extension).

$(TargetName) The base name of the primary output file for the build.

$(TargetPath) The absolute path name of the primary output file for the build (defined as drive + path + base name + file extension).

$(VCInstallDir) The directory that contains the C++ content of your Visual Studio installation. This property contains the version of the targeted Visual C++ toolset, which might be different that the host Visual Studio. For example, when building with $(PlatformToolset) = v140, $(VCInstallDir) contains the path to the Visual C++ 2015 installation.

$(VSInstallDir) The directory into which you installed Visual Studio. This property contains the version of the targeted Visual Studio toolset, which might be different that the host Visual Studio. For example, when building with $(PlatformToolset) = v110, $(VSInstallDir) contains the path to the Visual Studio 2012 installation.

$(WebDeployPath) The relative path from the web deployment root to where the project outputs belong. Returns the same value as RelativePath.

$(WebDeployRoot) The absolute path to the location of <localhost>. For example, c:\inetpub\wwwroot.

MSBuild Command Line

Build a project with default configuration:

msbuild MyProject.csproj

Build a project with a specific configuration:

msbuild MyProject.csproj /P:Configuration=Debug
msbuild MyProject.csproj /P:Configuration=Release

Build a project with a specific output path:
(Path starts at *.csproj folder)

msbuild MyProject.csproj /P:OutDir=.\bin\Debug\net20\;Configuration=Debug
Alternative is to update the "OutputPath" tag in the *.csproj file.

Build a project with a specific target framework, regardless of the one specified in the csproj file:

msbuild MyProject.csproj /P:TargetFrameworkVersion=v2.0;Configuration=Debug

Clean a project before rebuilding it:

msbuild MyProject.csproj /t:Clean;Rebuild /P:Configuration=Debug
There are several intermittent errors that cleaning (instead of just building) MIGHT fix. More testing is required.
The errors I encountered looked like settings from other versions of the project were leaking, somehow, into the compiling version.
(1) Sometimes the project built to the wrong Runtime Version, even though the TargetFrameworkVersion was specified.
(2) Sometimes the project thought it needed extra dependencies that other versions of the project needed, but this one did not.

Restore the dependencies and tools of a project
If there is more than one Solution or Project in the current folder, specify one

dotnet restore --no-cache --force-evaluate
dotnet restore MySolution.sln --no-cache --force-evaluate

Cleans the output of a project

dotnet clean
dotnet clean MySolution.sln

NuGet

How to make NuGet packages.

Nuspec File

1) Download nuget.exe
[Download nuget.exe]
2) Copy nuget.exe to the Solution directory of the project that will be included in the nuget package.
3) Open command prompt, Navigate to the Solution directory, run "nuget spec".
- A "ProjectName.nuspec" file will be generated based on the Solution.
4) Open ProjectName.nuspec and manually fill in the properties for: id, authors, owners, license, iconUrl, tags, dependencies
[Complete list of optional properties.]

The "id" property must be unique across nuget.org and contain only URL-compliant characters. It is recommended to prefix your company name, to help guarantee uniqueness. Namespace style names, with dot delimiters, are suggested. It is best if the "id" matches the namespace used in the code.
- If your package is a collection of sample code, the "id" should end with ".Sample".
[Search NuGet to verify id is not in use.]

The "version" property must be changed each time the contents of the package change.

"authors" is a comma-delimited list of names matching profile names on NuGet.org.
"owners" is a comma-delimited list of names matching profile names on NuGet.org. Optional.

"tags" is a space-delimited list of keywords and descriptors associated with the package.

The "description" and "releaseNotes" tags support Markdown formatting in their contents. This will not show up on NuGet's preview page, but it does once you publish the project.
- Note that hyperlink aliases don't work. A full web address will act as a hyperlink, but you cannot alias it with the [alias](link) syntax.

5) Add a list of *.dll files to be included in the package.

<package>
    <files>
        <file src='MyPath\MyLibrary.dll' target='lib\MyLibrary.dll' />
    </files>
</package>
- The path will start at the directory of the *.nuspec file.
- The target should start with "lib\".

It is recommended that *.dll files be placed in a framework-specific subfolder under "lib".
Example: target="lib\net46\MyLibrary.dll" indicates that the library relies on .Net 4.6

If a *.dll is not needed in the compiled client project, place it in "ref/" instead of "lib/". Your *.dll will not be copied to the client's output folder.

Any 3rd party library that your library relies on must be included as a file here.
In general, any *.dll in your library's bin folder should be included here.

6a) Add a list of content files to be included in the package (*.cs, *.html, *.txt, *.json, *.xml, etc)

<package>
    <files>
        <file src='MyPath\MyData.txt' target='content\MyData.txt' />
    </files>
</package>
- It is recommended to include a "readme.txt" file. It will be displayed when the package is installed.

These files will end up in the root directory of the client's project.

6b) Add a list of *.targets and *.prop files to be included in the package.

<package>
    <files>
        <file src='MyPath\MyTarget.targets' target='build\MyTarget.targets' />
    </files>
</package>

The appropriates references will be automatically added to the client's project file.

Many of the common macro values are only set during <Import Project="...\Microsoft.CSharp.targets" />. And importation of custom *.props files is inserted before that in the project file. Therefore, most macros cannot be used in custom *.props files.

If a property is not set and you try to use it, it will be equal to empty string.

7) Add existing NuGet packages that this one depends on.

<package>
    <group targetFramework="uap">
        <dependency id='nugetId' version='nugetVersion' />
    </group>
</package>

If you have a list of dependencies for (ex) targetFramework="net40", this list will be used for all targets 4.0 and above, unless you specify another group for one of the higher targets. So if you have dependencies for low frameworks, and none for higher ones, include an empty group for the first framework that has no dependencies.

AssemblyInfo Token Replacement

You can use tokens in the *.nuspec. They are formatted as a token name surrounded by dollar ($) signs.

  <package>
    <metadata minClientVersion="2.0">
      <id>MyId</id>
      <version>$version$</version>
    </metadata
  </package>

If you use tokens, you must build the NuGet package using "nuget pack Name.csproj" instead of "nuget pack Name.nuspec".

Otherwise you will get error "Value cannot be null or an empty string. Parameter name: value."

Create Package

1) Create and fill in the *.nuspec file.
2) Open command prompt, Navigate to the directory that contains *.nuspec and nuget.exe
3) Run "nuget pack ProjectName.nuspec" which creates file "ProjectName.Version.nupkg".

You can re-pack the package anytime the contents change.

Testing

1) Add a local NuGet source to Visual Studio.
1a) Tools menu > Options > NuGet Package Manager > Package Sources
1b) Click the "Add" button (the green plus-sign).
1c) Choose a source name and a directory for the local packages.
1d) Click "Ok".

This local source can be selected when adding packages through "Manage NuGet Packages".

2) Add the test package to your test project.
2a) Tools menu > NuGet Package Manager > Manage NuGet Packages for Solution
2b) Set "Package Source" to the local source.
2c) Select "Browse".
2d) Select the test package to install.

3) Run the appropriate tests.

Certificates

All NuGet packages must be signed with a certificate that is registered with NuGet.
[NuGet's post]
[Signed Packages]
[Signing Packages and list of trusted root authorities]
[Signing and Uploading Packages]

Signing a package provides protection against tampered content.
The signature is produced from a X.509 certificate.

NuGet only accepts certificates signed by a "trusted root authority" who is trusted by default by Windows.
In order words, you cannot use self-issued certificates.

This focuses on "Author Signatures", which is the type required by NuGet.

It sounds like, if you sign your package with a valid certificate today and publish it, then the package will remain valid after the certificate itself expires. Because the timestamp on the package is for a time the certificate was valid.

You can sign any number of packages with one certificate.

1) Buy a certificate from a trusted root authority approved by Microsoft.
- You should get a PKCS #12 file with *.pfx extension.
- Import this into Windows.
- Must have an RSA public key 2048 bits or greater.

1.5A) You should have the private key on your development computer.
- run certmgr.msc to view keys
- look under Intermediate Certification Authorities > Certificates > search by expiration date or name of company
- looks like a private key is only exportable (backup-able) if that ability was specified when the certificate was requested

1.5B) Or this - export certificate from the browser you used for the request and the certificate installation.
- Firefox > Options > Privacy & Security > scroll down to Certificates > View Certificates
- select Your Certificates > should see your new certificate there
- Backup certificate as a *.p12 file
- The p12 format is the same as the pfx format, so you can just change the extension

2) Export the certificate to "DER encoded binary X.509" format.
[How to Install OpenSSL]
[Download OpenSSL]
- Install OpenSSL
- Explorer > C:\OpenSSL-Win64\bin > run openssl.exe as administrator
- "pkcs12 -in <MyCertificate>.pfx -out <MyCertificate>.crt -nokeys -clcerts" (pull public certificate out of package, requires the password you set when creating the .pfx file)
- "x509 -inform pem -in <MyCertificate>.crt -outform der -out <MyCertificate>.cer" (convert to binary encoding (DER), no password required)

3) Register the certificate with NuGet. Look under Account Settings >> Certificates.

4) Sign the package with a timestamp.
- In command prompt, at the location of the *.nupkg file:
- "nuget sign MyPackage.nupkg -CertificateSubjectName <MyCertificateSubjectName> -Timestamper <TimestampServiceURL>"
- Example "nuget.exe sign MyPackage.1.0.0.nupkg -CertificatePath path_to_private_key.pfx -Timestamper http://sha256timestamp.ws.symantec.com/sha256/timestamp"
- this will update the <MyPackage> file so it is now signed

5) Verify the package.
- "nuget.exe verify MyPackage.1.0.0.nupkg -All"
- output should end with "Successfully verified package"

Publish

1) Create an account on NuGet.org.
2) Go to the page for uploading packages.
3) Click "Choose File" and select the local *.nupkg file.
4) Click "Upload".
5) Verify the information.
6) Click "Publish".

The package can now be searched for and installed by anyone using NuGet.

Pre Release

NuGet supports a naming convention to mark "alpha" and "beta" releases.
[Microsoft Page]

Update the "version" tag in your *.nuspec file to "<number>-alpha".
Or update the assembly attribute of you C# project to "[assembly: AssemblyInformationalVersion("<number>-alpha")]".

Pack and publish as normal. NuGet will not auto-install or recommend this "alpha" or "beta" version to anyone unless they check "Include Prerelease" while searching.

To install a pre-release from command line:

nuget install -IncludePrerelease MyPackage

You can technically use any string after the hyphen and NuGet will assume the package is prerelease, but the most recognized are:
alpha - work in progress or experimentation
beta - feature complete for next release but contains known bugs
rc - "release candidate" - feature complete and, if no bugs are found, will be the next release

If you use many different strings, NuGet will sort them alphabetically, assuming that the later ones are newer.

Patterns

For providing properties with default values that can be overridden per project:

<!-- in the Target -->
<!-- the default will only be set if the property value is empty -->
<CreateProperty Value="default_value_with_macros" Condition="'$(MyPropertyName)'==''">
    <Output TaskParameter="Value" PropertyName="MyPropertyName"/>
</CreateProperty>

<!-- override defaults in *.csproj -->
<!-- make sure your PropertyGroup is after Microsoft.CSharp.targets, so you can use macros -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
    <MyPropertyName>custom_value_with_macros</MyPropertyName>
</PropertyGroup>
<!-- NuGet custom targets will be imported after this -->

Considerations

When deciding how to design solutions and namespaces:
1) Any grouping of functionality that requires a third-party library needs its own namespace and its own NuGet package.
- that way the extra dependency is not forced on users that won't be using it