New Minimod: FluentGenerics–Interacting with Generic Types and Type-Definitions

Sometimes, from a concrete type, you need to find out if it implements a specific generic type or interface, and even more interesting, which concrete type arguments it uses in it’s implementation.

Since this information can be “hidden” somewhere in the type hierarchy, I created some helper extension methods that help finding this information and released them as a Minimod. What is a Minimod?

It can answer these simple questions:

Is List<Int32> an IEnumerable<T>? yes
If it is, what are the type parameters? Int32

Is Dictionary<Int32,String> an IDictionary<TKey,TValue>? yes
If it is, what are the type parameters? Int32,String

This is the test/example code generating them:

[Test]
public void PrintExamples()
{
    printExample(typeof(List<int>), typeof(IEnumerable<>));
    printExample(typeof(Dictionary<int, string>), typeof(IDictionary<,>));
}

private static void printExample(Type type, Type genTypeDef)
{
    bool isOfGenericType = type.IsOfGenericType(genTypeDef);

    Console.WriteLine("Is {0} an {1}? {2}",
                      type.GetPrettyName(),
                      genTypeDef.GetPrettyName(),
                      isOfGenericType ? "yes." : "no.");

    if (isOfGenericType)
    {
        Console.WriteLine("If it is, what are the type parameters? "
                          + type.GetGenericArgumentsFor(genTypeDef)
                                .Select(_ => _.GetPrettyName())
                                .JoinStringsWith(", "));
    }
}

Summary

The Minimod adds to System.Type the following extension methods:

  • bool IsOfGenericType(this Type type, Type genericTypeDefinition)
  • Type[] GetGenericTypesFor(this Type type, Type genericTypeDefinition)
  • Type GetGenericTypeFor(this Type type, Type genericTypeDefinition)
  • Type[] GetGenericArgumentsFor(this Type type, Type genericTypeDefinition)

Get it!

It is published to Nuget as a Minimod: NuGet gallery

Other minimods are also available there: Packages – NuGet gallery

Original source code is found at: minimod/minimods – GitHub

Advertisements

Reuse, Reuse, Reuse – do we need utility libraries? If not, what’s next? Minimods!

We love being productive. And there are tons of generic problems that we solve far too often. The .NET Base Class Library has plenty of functionality (compared to Java w/o Apache.Commons). But still there is much missing.

So, every developer has tons of snippets in his backyard, from where he digs up and copy-pastes class by class, method by method. Then, from time to time, in the name of reuse, we package those utilities in libraries called *.Common or *.Utils, and put them in our toolbox. Some of us (as a species) then publish their util-libraries as open source: Among them Rhino.Commons, Umbrella, Magnum and many more.

The cost of dependencies

The cost of an dependency is high. If you just need that little thing, but introduce a dependency to a big ball of (unrelated) mud – you’re better off copy-pasting exactly what you need. But event that is hard, because if you start writing utilities, then your utilities tend to depend on each other.

Good reads on this topic:

But still…

But still we do not want to reinvent the wheel on every project. So what to do?

Options

Lets just shortly list the options we have for reusing generic code – besides creating huge utility libraries:

  • Copy-paste
  • Creating very specific libraries: but who want’s the overhead of a DLL?
  • … IL-merge those very specific libraries
  • Utilize .NET modules; those are smaller than an assembly and can be linked into any assembly – that is what ILmerge does. But there is no tooling support for .NET modules in Visual Studio…

I think there is just one option left: Single-file distributions with utility-classes, that can be included as source.

But how to distribute them? How to version? How to upgrade?

Then, how to maintain them? Manual download, copy-paste? In times of NPanday and Nuget? Not really.

Minimods

With this in mind I started off something I’ll call Minimod for now. It is a rather small module, containing of source code only, that can be installed into any of your C# assemblies.

I’ll write more on how to create and publish a Minimod later (hopefully in combination with NPanday).

Definition

A Minimod is defined as follos:

  • it must consist of one file and be very specific (no StringExtensionsMinimo, LinqExtensionsMinimod, or MyUtilMinimod please!!)
  • Each Minimod must be in it’s own namespace in order to avoid extension-method conflicts.
  • A Minimod should only depend on .NET BCL or other Minimods

I also want tool-support for integrating it, as well as upgrade/remove.

Proof of Concept

I just started bundling some utilities in classes and created simple Nuget-Packages. This makes it very easy to install and upgrade the files.

image

Then I published those to the Nuget Gallery.

image

When installing, a file will be created in the subdirectory Minimods. I named it *.Generated.cs, because that will prevent ReSharper from complaining about things.

image

Preview of the imported file. Namespace does not fit (see issues).

image

Now we use them:

using Minimod.NestedDictionary;
using Minimod.PrettyText;
using Minimod.PrettyTypeSignatures;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var width = 22;
            Console.WindowWidth = width;

            var minimods = "Minimods are great! Go get them at Nuget.org, just by searching for 'minimod'.";

            Console.WriteLine(
                minimods
                .ShortenTo(width)
                );

            Console.WriteLine();

            Console.WriteLine(
                minimods
                .WrapAt(width)
                .JoinLines());

            var listPerKey =
                new Dictionary<string, List<string>>();

            Console.WriteLine();

            Console.WriteLine(
                listPerKey.GetType()
                .GetPrettyName()
                .ShortenTo(width));

            listPerKey.EnsureValueFor("key1");
            listPerKey.AddToCollection("key2", "one");
            listPerKey.AddToCollection("key2", "two");

            Console.WriteLine();

            Console.WriteLine("key1: " +
                String.Join(", ", listPerKey["key1"]));

            Console.WriteLine("key2: " +
                String.Join(", ", listPerKey["key2"]));

            Console.ReadKey();
        }
    }
}

The result

image

Still to be considered

  • Namespace should maybe be adjusted to the target-projects namespace + “.Minimods”? Or is it great having *.Minimod for all of them?
  • Id, description and versioning is all done manually now – want to automate this.
  • Haven’t tried with dependencies yet, but that should work.
  • Planning to use NPanday to automate the process of releasing and publishing Minimods ([#NPANDAY-372] Integrate with NuGet and NuGet Gallery (nuget.org))

What do you think? I’d be happy to get Feedback on the process!

I’ll also hopefully keep posting more Minimods.

Current source code is here: moved to minimod/minimods at GitHub (from Braindrops.MiniMods at GitHub)