mardi 6 octobre 2020

Using `GetMethod` on class implementing an interface with a default method implementation returns null

I have a couple interfaces (IMapFrom and IMapTo) that allow me to simplify my AutoMapper configurations. Each of the interfaces has a default implementation for the MapTo and MapFrom methods. I have a separate MappingProfile class that uses reflection to find all of the implementing classes, and invokes their map creation.

The aforementioned classes look like so:

public interface IMapFrom<T>
{
    void MapFrom(Profile profile) => profile.CreateMap(typeof(T), GetType());
}

public interface IMapTo<T>
{
    void MapTo(Profile profile) => profile.CreateMap(GetType(), typeof(T));
}

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
    }

    private void ApplyMappingsFromAssembly(Assembly assembly)
    {
        var types = assembly.GetExportedTypes()
            .Where(t => t.GetInterfaces().Any(i =>
                i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(IMapFrom<>) || 
                                    i.GetGenericTypeDefinition() == typeof(IMapTo<>))))
            .ToList();

        foreach (var type in types)
        {
            var instance = Activator.CreateInstance(type);
            var mapTo = type.GetMethod("MapTo");
            var mapFrom = type.GetMethod("MapFrom");
            mapTo?.Invoke(instance, new object[] {this});
            mapFrom?.Invoke(instance, new object[] {this});
        }
    }
}

If the class implementing the interfaces overrides the default interface implementations, the MappingProfile class works as desired. However, if the classes simply rely on the default implementations, mapTo and mapFrom in the ApplyMappingsFromAssembly method are both null.

For example, this class would not have its mappings applied successfully:

public class CreateJobCommand : 
        UpdateJobInputModel, 
        IMapFrom<UpdateJobInputModel>,
        IMapTo<Job>,
        IRequest<int>
{

}

How can I get the default implementations if they're not reimplemented in the inheriting class?





Aucun commentaire:

Enregistrer un commentaire