Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a generic extension method without specifying as many types

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. :(

like image 660
Dan Atkinson Avatar asked Apr 04 '13 16:04

Dan Atkinson


People also ask

How do you call an extension method?

To define and call the extension methodDefine a static class to contain the extension method. The class must be visible to client code. For more information about accessibility rules, see Access Modifiers. Implement the extension method as a static method with at least the same visibility as the containing class.

What are the types of extension methods in C#?

The most common extension methods are the LINQ standard query operators that add query functionality to the existing System. Collections. IEnumerable and System. Collections.

Can you add extension methods to an existing static class?

The main advantage of the extension method is to add new methods in the existing class without using inheritance. You can add new methods in the existing class without modifying the source code of the existing class. It can also work with sealed class.


2 Answers

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.)

like image 185
Jon Skeet Avatar answered Sep 18 '22 21:09

Jon Skeet


It is not possible to infer some, but not all, of the type arguments, no.

You can either:

  1. Specify all of the generic arguments.

  2. Ensure that all of the generic arguments can be inferred. (Not always possible, or the compromises needed to allow inference may not be desirable.)

  3. Break the method up into multiple methods such that one method infers the generic arguments and one does not.

like image 44
Servy Avatar answered Sep 18 '22 21:09

Servy