c# - 具有基类和子类的扩展方法

标签 c# inheritance reflection extension-methods

更新

请求重新打开,因为其他 SO 答案没有解决方案,但对该问题的评论之一有一个我想接受的解决方案,因为它适用于该场景。

原始问题

我在使用选择适当扩展方法的非抽象基类和子类编写扩展方法时遇到问题。

Example Code

我下面有一个非常简单的示例(从一个更大的项目中抽象出来),它使用扩展方法“Run”。预期输出列在每个类旁边的注释中。

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())));
    }
}

这是我迄今为止的尝试,但必须有一种更简洁的方法来做到这一点:

  1. 无类型检查 - 导致仅使用 Parent 扩展方法(Parent、Parent、Parent)
  2. 显式类型检查 - 正确的输出,但必须显式检查每种扩展可能性(ChildA、Parent、Parent)的类型
  3. 尝试将.ChangeType 转换为动态类型 - 由于扩展无法捕获动态类型(无输出),因此出现运行时异常
  4. 尝试使用反射进行通用转换 - 尚未完全可操作,但不确定方法是否有效

尝试列表

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;   
    }

}

最佳答案

ParentChildA创建两个扩展方法,您可以使用dynamic将关联移至运行时。

Console.WriteLine(string.Join(", ", commands.Select(c => Extensions.Run(c as dynamic)))); 

关于c# - 具有基类和子类的扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30645441/

相关文章:

reflection - 在 Groovy 中使用 invokeMethod 动态实现接口(interface)

c# - 如何将 DbSet<T> 转换为 List<T>

c# - 如何从/bin 目录中加载所有程序集

c# - 在 ListView 中绘制水平线以显示放置位置

c# - Swagger C# 枚举生成 - 底层 int 值与原始枚举不匹配

c# - 条件运算符会感到困惑,但为什么呢?

c# - 如何使用反射在 C# 中获取自动属性的默认值?

c# - 获取 .NET WEB 应用程序文件系统根目录的通用方法

c++ - oop - C++ - 实现特定类型行为的正确方法?

java - 协助构建具有多个类别的体育游戏