I am having trouble writing extension methods with non-abstract base classes and sub-classes that select the appropriate extension method.
I have a very simple example below (abstracted from a much bigger project) that uses the extension method "Run". The expected output is listed in the comment next to each class.
public class Parent { }; // Should output "Parent"
public class ChildA : Parent { }; // Should output "Child A"
public class ChildB : Parent { }; // Should output "Parent"
// Expected Output: ChildA, Parent, Parent
public class Program
{
public static void Main()
{
var commands = new List<Parent>() { new ChildA(), new ChildB(), new Parent() };
Console.WriteLine(string.Join(", ", commands.Select(c => c.Run())));
}
}
Here are my attempts so far, but there has to be a cleaner way to do this:
- No type-checking - Results in the Parent extension method being used exclusively (Parent, Parent, Parent)
- Explicit type checking - Right output, but have to explicitly check types for each extension possibility (ChildA, Parent, Parent)
- Attempted Convert.ChangeType to dynamic type - Run-time exception since extension won't catch the dynamic type (no output)
- Attempted generic cast with reflection - not quite operational yet, but not sure if approach is even valid
List of attempts
public static class Extensions
{
public static string Run(this ChildA model)
{
return "ChildA";
}
public static string Run(this Parent model)
{
return model.Run1(); // Change to test different approaches
}
public static string Run1(this Parent model) // No type-checking
{
return "Parent";
}
public static string Run2(this Parent model) // Explicitly check sub-types
{
if (model is ChildA)
return ((ChildA)model).Run();
else
return "Parent";
}
public static string Run3(this Parent model) // Attempted dynamic type conversion
{
if (model.GetType().BaseType == typeof(Parent))
{
dynamic changedObj = Convert.ChangeType(model, model.GetType());
return changedObj.Run();
}
else
return "Parent";
}
public static string Run4(this Parent model) // Attempted reflected generic type conversion
{
if (model.GetType().BaseType == typeof(Parent))
{
var method = typeof(Extensions).GetMethod("Cast");
var generic = method.MakeGenericMethod(new[] { model.GetType() });
//var generic = generic.Invoke(new object(), null);
//return generic.Run();
return "Not working yet";
}
else
return "Parent";
}
public static T Cast<T>(this object input)
{
return (T) input;
}
}
Aucun commentaire:
Enregistrer un commentaire