Retrieve generic contract names for Managed Extensibility Framework Edit
Found the original contract name resolution by .NET MEF, the code below is not useful anymore. See response!

My issue was to use existing code, to make a MEF ExportFactory, imported via [Import] attribute to a property, return instances of Moq mocks (for unit testing). Problem was, that the original code always used the Type.FullName property value as contract name. This worked fine for non-generic types, but not for generics.

Generic FullName is like:


My.Assembly.GenericType`1[My.Assembly.InnerType]



but MEF expects a name like:


My.Assembly.GenericType(My.Assembly.InnerType)



The complete unit test code actually extends the MEF ExportProvider class, to register ExportDefinition instances for an ExportFactory and it's ProductDefinition. The contract name goes to a metadata dictionary, using the key CompositionConstants.ExportTypeIdentityMetadataName.

This following code is only for the contract name conversion. It calls itself recursively, for generic arguments which are generic themselves. The regular expression matches by the `[digits] name extension, used by .NET for generic types. It would be nice to see a generally better way, or already existing functions from MEF, if such exists. 

Edit: I added the incrementor and code for open (unspecified) generics, which have names with indexed curly brackets: instead of IMyType&lt;string,int&gt; IMyType&lt;,&gt;, resolved to contract name IMyType({0},{1}). Regex has also been changed to match, if no type names come after `[digits].

private static readonly Regex GenericRegex = 
    new Regex(@"^(?&lt;fullNameNonGeneric&gt;\S+?)`\d+(\[.*\])*$", 
        RegexOptions.Compiled);


public static string ResolveGenericMefContractName(this Type type)
{
    return ResolveGenericMefContractName(type, new IndexIncrementor());
}

private static string ResolveGenericMefContractName(Type type, IndexIncrementor incrementor)
{
    var fullName = type?.FullName;
    if (fullName == null)
    {
        return null;
    }
    var match = GenericRegex.Match(fullName);
    if (!match.Success)
    {
        return type.FullName;
    }

    var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;
    var genericArgs = type.GetGenericArguments();

    return fullNameNonGeneric + "(" +
        string.Join(",", genericArgs.Select(
            ga =&gt; ResolveGenericMefContractName(ga, incrementor) 
            ?? "{" + incrementor.GetAndIncrementValue() + "}")) 
        + ")";
}

private class IndexIncrementor
{
    private int _value;

    public int GetAndIncrementValue() =&gt; _value++;
}
The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.

This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):

Namespace:


System.ComponentModel.Composition



Static method:


AttributedModelServices.GetContractName(Type)



Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...