Skip to content

Commit

Permalink
Match the most specific image source type
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrozsival committed Jan 19, 2024
1 parent c951cfb commit a39e019
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,57 @@ public ImageSourceServiceBuilder(IEnumerable<ImageSourceRegistration> registrati

public (Type ImageSourceType, Type ImageSourceServiceType) FindImageSourceToImageSourceServiceTypeMapping(Type type)
{
List<(Type ImageSourceType, Type ImageSourceServiceType)> matches = new();

foreach (var mapping in _typeMappings)
{
var imageSourceType = mapping.Key;
var imageSourceServiceType = mapping.Value;

if (imageSourceType.IsAssignableFrom(type) || type.IsAssignableFrom(imageSourceType))
{
return (imageSourceType, imageSourceServiceType);
var imageSourceServiceType = mapping.Value;
matches.Add((imageSourceType, imageSourceServiceType));
}
}

throw new InvalidOperationException($"No image source service found for {type.FullName}");
return matches switch
{
[var match] => match,
[] => throw new InvalidOperationException($"Unable to find any configured {nameof(IImageSource)} corresponding to {type.Name}."),
_ => SelectTheMostSpecificMatch(matches),
};
}


public void AddImageSourceToImageSourceServiceTypeMapping(Type imageSourceType, Type imageSourceServiceType)
{
Debug.Assert(typeof(IImageSource).IsAssignableFrom(imageSourceType));
Debug.Assert(typeof(IImageSourceService).IsAssignableFrom(imageSourceServiceType));

_typeMappings[imageSourceType] = imageSourceServiceType;
}

private static (Type ImageSourceType, Type ImageSourceServiceType) SelectTheMostSpecificMatch(List<(Type ImageSourceType, Type ImageSourceServiceType)> matches)
{
var bestImageSourceTypeMatch = matches[0].ImageSourceType;
var bestImageSourceServiceTypeMatch = matches[0].ImageSourceServiceType;

foreach (var (imageSourceType, imageSourceServiceType) in matches[1..])
{
if (imageSourceType.IsAssignableFrom(bestImageSourceTypeMatch)
|| bestImageSourceTypeMatch.IsInterface && imageSourceType.IsClass)
{
bestImageSourceTypeMatch = imageSourceType;
bestImageSourceServiceTypeMatch = imageSourceServiceType;
}

// TODO we could still improve this to detect truly ambiguous cases, like:
// - FileImageSourceA (implements IFileImageSource) -> X
// - FileImageSourceB (implements IFileImageSource) -> Y
// -> find closest match to `IFileImageSource`
}

return (bestImageSourceTypeMatch, bestImageSourceServiceTypeMatch);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void ThrowsWhenMissingService()

var ex = Assert.Throws<InvalidOperationException>(() => provider.GetRequiredImageSourceService(new FileImageSourceStub()));

Assert.Contains(nameof(IFileImageSource), ex.Message, StringComparison.Ordinal);
Assert.Contains(nameof(FileImageSourceStub), ex.Message, StringComparison.Ordinal);
}

[Fact]
Expand Down

0 comments on commit a39e019

Please sign in to comment.