简体   繁体   中英

Getting a generic method to infer the type parameter from the runtime type

I have some extension methods for an abstract base class, let's say Pet , that themselves call a generic method that takes in that type parameter.

public static Pet_ExtensionMethods
{
    public static T PermuteFromData<T>(this T thisPet, string data) where T : Pet
    {
        T newPet = new SomeDeserializer().Deserialize<T>(data);
        newPet.someProperty = thisPet.someProperty;
        return newPet;
    }
}

This has worked great for me, as I can say things like:

Dog newDog = existingDog.PermuteFromData(dogData);
Cat newCat = existingCat.PermuteFromData(catData);

And all with the same base implementation and no code duplication.

But I recently discovered a disturbing problem! If I go:

Pet myPet = existingDog;
string petData = dogData;
Pet newPet = myPet.PermuteFromData(petData);

I want the behavior to be the same, but now the compiler is electing to run PermuteFromData<Pet> which in turn calls Deserialize<Pet> , which in the bowels of some library I don't control tries to go Activator.CreateInstance(typeof(T)) - which throws an Exception for trying to create an instance of an Abstract class!

The only workaround I've found is to vomit out the following code to get the correct generic method using the run-time type:

public static T PermuteFromDataFix<T>(this T thisPet, string data) where T : Pet
{
    return (T) typeof(Pet_ExtensionMethods).GetMethod("PermuteFromData")
        .MakeGenericMethod(new Type[] { thisPet.GetType() })
        .Invoke(null, new object[] { thisPet, data });
}

For the love of god, is there any other way? Having a hard coded string with the name of a method in a class is just unacceptable.

I have a whole bunch of extension methods like this where the generic method needs to infer the runtime type, not the compile time type. Someone told me I can get around this with a clever use of dynamic . Is that so?

You can try using dynamic , but I'm not sure you can do this using extension method syntax.

Try this one first:

Pet_ExtensionMethods.PermuteFromData((dynamic)pet, petData);

It should work as expected. Then you can try

((dynamic)pet).PermuteFromData(petData);

but I'm not sure it will resolve to correct method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM