Invariance, Covariance and Contravariance

Polymorphism

We can assign a derived instance to a base reference, this is trivial 🙂

Base ref1 = new Derived();

It also work with generic classes, as long as the type parameter is the same:

GenericBase<Base> ref2 = new GenericDerived<Base>();
GenericBase<Derived> ref3 = new GenericDerived<Derived>();

Invariance

But we have an error if we try to apply the same principle to the type parameter:

GenericBase<Base> ref4 = new GenericBase<Derived>();  // <= This is not allowed!

The reason is that for a type parameter, by default, we don’t have any polymorphic behavior. We can only use the type originally specified. In this case we say that the type parameter is Invariant.

The ability to have a polymorphic behavior on a type parameter is possible throught the concept of Covariance (and Contravariance, which is the opposite). If a type parameter is either Covariant or Contravariant we say it’s Variant. In .Net Variance in only supported for interfaces and delegates.


Covariance

Is the ability to assign a derived type to a base type parameter. Can be specified by adding the “out” keyword to the type parameter definition.

ICovariantInterface <Base> ref5 = new CovariantBaseClass<Derived>();
ICovariantInterface<Base> ref6 = new CovariantDerivedClass<Derived>();

An example of Covariance in .Net is the IEnumerable interface:

IEnumerable<Base> ref7 = new List<Derived>();

A Covariant type parameter can only be used as return type (hence the “out”).


Contravariance

Is the opposite of the Covariance, it allows to assign a base type to a derived type parameter. Can be specified by adding the “in” keyword to the type parameter definition.

IContravariantInterface<Derived> ref8 = new ContravariantBaseClass<Base>();
IContravariantInterface<Derived> ref9 = new ContravariantDerivedClass<Base>();

An example of Contravariance in .Net is the Action delegate:

Action<Base> action = (Base p) => { };
Action<Derived> ref10 = action;

A Contravariant type parameter can only be used as argument type (hence the “in”). Is used for instance when we want to pass an action that works for the base type to a method that accepts an action that works for the derived type parameter.

ApplyActionToDerived(action, new Derived());

Given:

void ApplyActionToDerived(Action<Derived> action, Derived target)
{
    action(target);
}

Here are the definitions of the classes and interfaces used in this examples:

public class Base
{ }

public class Derived : Base
{ }

public class GenericBase<T>
{ }

public class GenericDerived<T> : GenericBase<T>
{ }

public interface ICovariantInterface<out T>
{
    T ValidCovariantMethod();
    bool InvalidCovariantMethod(T argument); // <= This is not allowed!
}

public class CovariantBaseClass<T> : ICovariantInterface<T>
{
    public T ValidCovariantMethod()
    {
        throw new NotImplementedException();
    }
    public bool InvalidCovariantMethod(T argument)
    {
        throw new NotImplementedException();
    }
}

public class CovariantDerivedClass<T> : CovariantBaseClass<T>
{ }

public interface IContravariantInterface<in T>
{
    bool ValidContravariantMethod(T argument);
    T InvalidContravariantMethod(); // <= This is not allowed!
}

public class ContravariantBaseClass<T> : IContravariantInterface<T>
{
    public bool ValidContravariantMethod(T argument)
    {
        throw new NotImplementedException();
    }
    public T InvalidContravariantMethod()
    {
        throw new NotImplementedException();
    }
}

public class ContravariantDerivedClass<T> : ContravariantBaseClass<T>
{ }
Advertisements

Adding Drag & Drop to a Windows Forms TextBox to get a file path

As first thing we have to set the AllowDrop property of the TextBox to True from the designer.

After this we have to handle 2 events to manage when a file is dropped into the TextBox in order to print its path. These events are:

  • DragEnter: defines what to do against any attempt to drop something into the TextBox, based on which kind of item we are trying to drop. With this event we can allow only some kind of item to be dropped to our control. For our purpose we have to specify that we are interested just in file drops.
  • DragDrop: defines what to do when an allowed item is dropped to our control. In our case we want to extract the file path and to print in in the TextBox itself.
private void textXml_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
        ? DragDropEffects.Link
        : DragDropEffects.None;
}

private void textXml_DragDrop(object sender, DragEventArgs e)
{
    ((TextBox)sender).Text =
        ((string[])e.Data.GetData(DataFormats.FileDrop, false)).First();
}

Integrating Identity Framework (Individual User Accounts)

When we select Individual User Accounts as Authentication Method while creating a new project (MVC Framework in this case) we have Identity Framework added to our solution with a basic default configuration.

Here is a list of the main components that are added:

  • AccountController: it handles the user’s registration, login and logout. It includes as well user’s validation and complementary workflows, such as the Reset Password workflow and the Forget Password workflow. Is a sample controller with the most common configuration that can be customized for our needing.
  • AccountViewModels/Account Views: view models and views for the AccountController.
  • ManageController: it handles the user management pages in our MVC Framework application. Is complementary with the AccountController. Is a sample controller with the most common configuration that can be customized for our needing.
  • ManageViewModels/Manage Views: view models and views for the ManageController.
  • IdentityModels: here we can find the Identity EF Context. It works as for a normal EF Code First application. The ApplicationUser class can be extended to add custom properties that we want to store for our users.

The IdentityConfig.cs and Startup.Auth.cs files are added as well under the App_Start folder. This files contain many classes that can be used to configure many behaviors, such as the email/SMS services to send email and SMS, the password strength requirements, the cookie authentication policy and so on.

Identity Framework uses OWIN (Open Web Interface for .Net) to decouple our application from the web server. This allow the application to work with different configurations of OS + WebServer, without being tied to Windows and IIS.


Setting the target DB for Identity Framework Data

As for any other EF Code first application we can do this by setting the connection string when we create the context:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base(@"Data Source=.\SQLEXPRESS;Initial Catalog=TestIdentityDB;Integrated Security=True", throwIfV1Schema: false)
    {
    }
 
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

At the first attempt to access the DB this will be created (as for any normal EF Code First application). Here is its general structure:

The tables are all empty. If we try to register a new user a record will be created into the AspNetUsers table. Here is how it looks like:


Setting an action to require authentication

We can use the Authorize attribute to specify an action that requires authentication. An user that isn’t logged in will be sent to the login page if he tries to access the action.

[Authorize]
public ActionResult AuthenticatedPage()
{
    return View();
}

From the view is always possible to access the current user’s information through the User.Identity object:

@using Microsoft.AspNet.Identity
 
@{
    ViewBag.Title = "AuthenticatedPage";
}
 
<h2>AuthenticatedPage</h2>
<h3>Welcome @User.Identity.GetUserName()</h3>

Setting an action to not require authentication

The Authorize attribute can be set also at controller-level. This means that all the controller’s actions will inherit the attribute without needing a specific configuration. In this scenario where the authentication is required as default behavior we can use the AllowAnonymous attribute to specify that an action shouldn’t require authentication.

[Authorize]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
 
        return View();
    }
 
    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
 
        return View();
    }
 
    [AllowAnonymous]
    public ActionResult AuthenticatedPage()
    {
        return View();
    }
}

Setting an action to require role-based authentication

In addition to just requiring our user to be somehow authenticated in order to access a certain action, we can also require that the user is part of some authorization group (administrators for instance). In order to do this we need, first of all, to have users associated with roles into our Identity database. This can be easily done through a custom EF Initializer that will seed our Code First database with some basic user and role:

public class IdentityInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
    protected override void Seed(ApplicationDbContext context)
    {
        var passwordHasher = new PasswordHasher();
 
        var adminRole = new IdentityRole("Admin");
        var testRole = new IdentityRole("Test");
 
        var adminUser = new ApplicationUser
        {
            UserName = "admin@admin.com",
            Email = "admin@admin.com",
            PasswordHash = passwordHasher.HashPassword("admin"),
            SecurityStamp = Guid.NewGuid().ToString()
        };
        adminUser.Roles.Add(new IdentityUserRole
        {
            UserId = adminUser.Id,
            RoleId = adminRole.Id
        });
 
        var testUser = new ApplicationUser
        {
            UserName = "test@test.com",
            Email = "test@test.com",
            PasswordHash = passwordHasher.HashPassword("test"),
            SecurityStamp = Guid.NewGuid().ToString()
        };
        testUser.Roles.Add(new IdentityUserRole
        {
            UserId = testUser.Id,
            RoleId = testRole.Id
        });
 
        //Creates Roles
        context.Roles.Add(adminRole);
        context.Roles.Add(testRole);
 
        //Creates Users
        context.Users.Add(adminUser);
        context.Users.Add(testUser);
    }
}

Here is what the code above will insert into the database:

Now that our users are linked to roles we can specify, for instance, an action that will be accessible only for users in the “Admin” group. An user that isn’t part of that group will be sent to the login page if he tries to access the action. We can do this in a very easy way by passing some argument to the Authorize attribute.

[Authorize(Roles = "Admin")]
public ActionResult AuthenticatedPage()
{
    return View();
}

Defining/Calling a SP with a Table Type parameter

Let’s take this table “MyTable” as example:

Let’s say that we want to have a SP that allows us to add several items to this table in a single call. Among the many ways that we have to achieve this result, one of the cleaner is to send the new items all together in a Table Type parameter. Here is how to do it.


1) Creating a new Table Type parameter under Programmability/Types/User-Defined Table Types:

CREATE TYPE [dbo].[MyTableItemType] AS TABLE(
        [Name] [nvarchar](50) NOT NULL,
        [Value] [nvarchar](50) NOT NULL
)
GO

2) Creating a new SP that accepts a parameter of type MyTableItemType and use it to add the items to the table:

CREATE PROCEDURE [dbo].[MyTableAddMultipleItems]
        @items MyTableItemType READONLY
AS
BEGIN
        insert into MyTable (Name, Value)
        select Name, Value from @items
END

3) Calling the new SP and passing the Table Type parameter to it:

const string conStr = @"Data Source=.\sqlexpress;Initial Catalog=Test;Integrated Security=True";
using (var con = new SqlConnection(conStr))
{
    con.Open();
    using (var cmd = new SqlCommand("MyTableAddMultipleItems", con)
    {
        CommandType = CommandType.StoredProcedure
    })
    {
        //Creating the table parameter
        var itemsTable = new DataTable();
        itemsTable.Columns.Add("Name");
        itemsTable.Columns.Add("Value");
        itemsTable.Rows.Add(new object[] { "Name 1", "Value 1" });
        itemsTable.Rows.Add(new object[] { "Name 2", "Value 2" });
        itemsTable.Rows.Add(new object[] { "Name 3", "Value 3" });
        itemsTable.Rows.Add(new object[] { "Name 4", "Value 4" });
        itemsTable.Rows.Add(new object[] { "Name 5", "Value 5" });
 
        //Sending the table parameter
        cmd.Parameters.AddWithValue("items", itemsTable);
        cmd.ExecuteNonQuery();
    }
    con.Close();
}

Verifying that a mocked method have been called with Moq

[Test]
public void It_Should_Call_The_Number_Generator_Service()
{
    var result = _numbersProvider.GetNumbersCollection(10);
 
    //We are checking that the GetNumber()
    //method has been called exactely 10 times
    _numberGeneratorServiceMock.Verify(m => m.GetNumber(It.IsAny<int>(), It.IsAny<int>()),
        Times.Exactly(10));
 
    //We can also check that the mocked method
    //has been called with the desired parameters
    _numberGeneratorServiceMock.Verify(m => m.GetNumber(It.Is<int>(min => min == 1), It.Is<int>(max => max == 10)),
        Times.Exactly(10));
}

Is possible to reset the calls on a mock object by calling the ResetCalls() method. In this way is possible to test it again against a different condition.

Performing a Join on EF with Linq or Lambda expressions

Linq

Here is an example on how to join two entities (wCompPlayers and wCompPlayerTeams) to search for a player given surname and team id.

public PlayerModel GetBySurnameAndTeamId(string surname, int teamId)
{
    return (
        from p in _context.wCompPlayers
        from pt in _context.wCompPlayerTeams
        where p.IdPlayer == pt.IdPlayer
            && string.Equals(p.Surname, surname) && pt.IdTeam == teamId
        select p
        ).ToList().Select(CreatePlayerModel).FirstOrDefault();
}

Notice that we use the ToList() method to force the query to be evaluated and to have a list of results. In this way all the next steps will be evaluated only using Linq, without adding complexity to the generated underlying SQL.


Lambda

Here is the same search made with a Lambda expression. Notice that in this case we are using the AsEnumerable() method as we was using the ToList() method in the previous example: all the next steps will be evaluated without adding complexity to the generated underlying SQL.

public PlayerModel GetBySurnameAndTeamId(string surname, int teamId)
{
    return
        _context.wCompPlayers.Join(_context.wCompPlayerTeams,
            p => p.IdPlayer, pt => pt.IdPlayer, (p, pt) => new { p, pt })
            .Where(m => string.Equals(m.p.Surname, surname) && m.pt.IdTeam == teamId)
            .AsEnumerable().Select(m => CreatePlayerModel(m.p)).FirstOrDefault();
}

The Join() method accepts 4 parameters:

  • The object to join
  • An expression which returns the original object’s key to use for the join
  • An expression which returns the joined object’s key to use for the join
  • An expression which returns the joined object

Adding a TFS managed solution to GitHub

Working with VS is quite common to use TFS for our source control. But what if we want to move or just to publish our code on GitHub for other people to view or to contribute? Here is how to do it with just the GitHub website and VS (Visual Studio Tools for Git plugin needed).


1) First of all we need to create a new remote repository for our solution under the GitHub website:


2) With a free GitHub account we can only create a public repository, so basically the only thing we need to specify is the repository name:


3) After the remote repository has been created we can get its link, that is returned for us by GitHub.


4) We can use the link under VS to clone the remote repository (1) to a synchronized local repository folder (2) in our machine:


5) From now on every update we’ll do to our local repository folder will be committable to Git through the VS IDE, the command line or external tools such as SourceTree. Unlike TFS the Git tracking is not related with a specific project file, so every file (even if not included in the solution) will be tracked, compared and synchronized.

What we can do at this point is to copy our solution to the local repository folder. If we open it VS will automatically switch to Git as source control system (even if the solution was associated with TFS) because is able to detect the Git local repository.

If we prefer we can of course remove the TFS association before copying the solution. In this way, if someone will download our code, VS won’t try to connect to our TFS server.

Another option is to create a brand new solution just for Git and to add all the content from the original solution via copy/paste + “Include in Project”.


6) Before committing our local repository to the remote one is a good idea to add a .gitignore file to our solution in order to automatically exclude everything we don’t want to be sent to Git (the /bin folder for instance). Of course we could specify every time what to include and what not to include as we do in TFS, but in this way it will be easier and quicker and we’ll be sure that we’ll be always applying the same rules. We can ask Visual Studio to generate this file for us, with all the necessary configuration already included. Here is what to do in order to add it to the solution.

After added this file we can commit while including everything (with the “Include All” command) being sure that all the files referred by the .gitignore will be excluded anyway.


7) When we are happy with the solution we have in our local repository folder we can commit it to the remote one. To do this we first use the “commit” command to commit the changes we did in our local repository folder to the local repository. Then we use the “push” (first time) and “sync” commands to synchronize our local repository with the remote one:


8) Finally we can see our solution on GitHub:

Is a good practice to add a README.md file to the GitHub repository. This file will be automatically displayed in the repository’s page and can be used to contain a short description/guide about the project.