Daren Dahl
Daren Dahl

Reputation: 13

Calling a generic extension method with reflection

I am trying to invoke a generic extension method with a dynamic type but I keep getting an error.

GenericArguments[0], 'DifferenceConsole.Name', on 'DifferenceConsole.Difference'1[T] GetDifferences[T](T, T)' violates the constraint of type 'T'.

In the code below, I have tried commenting out the dynamic type and just hardcoding a type that should work (Name) but I get the same error. I don't understand why I am getting the error. Any advice?

public static class IDifferenceExtensions
{
    public static Difference<T> GetDifferences<T>(this T sourceItem, T targetItem) where T : IDifference, new()
    {
        Type itemType = sourceItem.GetType();

        foreach (PropertyInfo prop in itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            DifferenceAttribute diffAttribute = prop.GetCustomAttributes(typeof(DifferenceAttribute), false).FirstOrDefault() as DifferenceAttribute;

            if (diffAttribute != null)
            {
                if (prop.PropertyType.GetInterfaces().Contains(typeof(IDifference)))
                {
                    object sourceValue = prop.GetValue(sourceItem, null);
                    object targetValue = prop.GetValue(targetItem, null);

                    MethodInfo mi = typeof(IDifferenceExtensions)
                        .GetMethod("GetDifferences")
                        .MakeGenericMethod(typeof(Name));  // <-- Error occurs here
                        //.MakeGenericMethod(prop.PropertyType);

                    // Invoke and other stuff


                }
                else
                {
                    // Other stuff
                }
            }
        }

        //return diff;
    }
}

public class Name : IDifference
{
    [Difference]
    public String FirstName { get; set; }

    [Difference]
    public String LastName { get; set; }

    public Name(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }
}

public interface IDifference
{

}

public class Difference<T> where T: IDifference, new()
{
    public T Item { get; set; }

    public Difference()
    {
        Item = new T();
    }
}

Upvotes: 1

Views: 454

Answers (1)

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174319

Name doesn't have a public, parameterless constructor.
However, you constrained T to IDifference, new(), meaning that every type used as generic parameter has to implement IDifference and must have a public, parameterless constructor.

BTW: IDifferenceExtensions is a really poor name for a static class. The I prefix is usually reserved for interfaces.

Upvotes: 1

Related Questions