Search code examples
c#genericsgeneric-programming

Retrieving the unclosed type of a generic type closing a generic type


I’m having an issue (probably due to my lack of familiarity of C# generics) in getting the unclosed type of a generic. I have several methods that look rather similar to the following except for the explicit validator interface in use.

public IEnumerable<IDeleteValidator<T>> GetDeleteValidators<T>()
{
    var validatorList = new List<IDeleteValidator<T>>();
    foreach (var type in GetRecursiveBaseTypesAndInterfaces(typeof(T)))
    {
        var validatorType = typeof(IDeleteValidator<>).MakeGenericType(type);
        var validators = ObjectFactory
            .GetAllInstances(validatorType).Cast<IDeleteValidator<T>>();
        validatorList.AddRange(validators);
    }
    return validatorList;
}

The method GetRecursiveBaseTypesAndInterfaces does as it says and gathers all base types and interfaces of a given type. So what I'm eventually doing is getting the unclosed type of the explicit validator interface and getting it's type as closed on each of the original type T's base classes and interfaces. This works great, however I'd like to clean up my code and accomplish this in a more generic form than above

knowing that any validator of T will extend IValidator (as bellow)

public interface IDeleteValidator<in T> : IValidator<T> {}

My uncompleted attempt at a generic version of the above method looks like:

public IEnumerable<TValidator> GetValidators<T, TValidator>() 
    where TValidator : IValidator<T>
{
    var validatorList = new List<TValidator>();
    foreach (var type in GetRecursiveBaseTypesAndInterfaces(typeof(T)))
    {
        var unclosedType = ???
        var validatorType = typeof(unclosedType).MakeGenericType(type);
        var validators = ObjectFactory
            .GetAllInstances(validatorType).Cast<TValidator>();
        validatorList.AddRange(validators);
    }
    return validatorList;
}

How do I define unclosedType (or restructure the method) to do the same work as the original method with a call to

GetValidators<Whatever, IDeleteValidator<Whatever>>();

Or would it be possible to refine my method more so as a call like the following would be sufficient?

GetValidators<IDeleteValidator<Whatever>>();

Solution

  • I didn't quite follow the question (more due to my sleepiness than anything else), but are you after:

    var unclosedTyped = type.GetGenericTypeDefinition();
    

    ? (See the docs for details.)