Calling a generic extension method without specifying as many types

c#, extension-methods, lambda

Solution

No, you either have to specify all the type arguments, or none of them. There's no "partial" type inference.

However, one way you can sometimes get away with this is to have one generic method with a single type argument which returns an instance of a generic class, and then use type inference on that to do the rest - or vice versa. In this case, it might actually be best to separate the attribute fetching from the rest anyway:

something.GetPropertyAttributes(x => x.SomePublicString)
         .FirstAttribute<StringLengthAttribute>();

Here the first method call infers `T` and `TProperty` - and just returns an `IEnumerable<Attribute>` and `FirstAttribute` would just do the `OfType` / `FirstOrDefault` calls. (You might even decide that you don't need `FirstAttribute`, given that it's pretty simple to call `OfType` and `FirstOrDefault` yourself.)

Problem

Here is a snippet of a class I use for testing Type extension methods: ``` class Something { [StringLength(100, MinimumLength = 1, ErrorMessage = "Must have between 1 and 100 characters")] public string SomePublicString { get; set; } } ``` I have the following extension method: ``` public static class TypeExtensions { public static TAttributeType GetCustomAttribute<T, TAttributeType, TProperty>(this T value, Expression<Func<T, TProperty>> propertyLambda, bool inherit = false) { var type = typeof(T); var member = (MemberExpression)propertyLambda.Body; var propertyInfo = (PropertyInfo)member.Member; var customAttributes = propertyInfo.GetCustomAttributes(typeof(TAttributeType), inherit); return customAttributes.OfType<TAttributeType>().FirstOrDefault(); } } ``` Usage in a unit test: ``` 1: var something = new Something(); 2: var actual = something.GetCustomAttribute<Something, StringLengthAttribute, string>(x => x.SomePublicString); 3: actual.MinimumLength.Should().Be(1); 4: actual.MaximumLength.Should().Be(100); 5: actual.ErrorMessage.Should().Be("Must have between 1 and 100 characters"); ``` This returns a passing test (using FluentAssertions). However, I'd like to get the method call to GetCustomAttribute() in line 2 down to the following: ``` var actual = something.GetCustomAttribute<StringLengthAttribute>(x => x.SomePublicString); ``` Is this possible? Am I missing something? Maybe I'm on a caffeine crash. :(

Original source