如何在抽象类中调用方法

时间:2017-03-18 16:17:40

标签: c#

type message struct {
   queue chan string
}

func (m *message) init() {
    m.queue = make(chan string, 10)
}

我想调用public abstract class BaseClass { protected virtual int getValue() { return 1; } } 方法。

getValue

此代码有错误。

  

非静态方法需要目标

但是,我无法创建BaseClass的实例,因为它是抽象类。 所以,我正在使用扩展typeof(BaseClass) .GetMethod("getValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) .Invoke(null, new object[] { }); 的虚拟类。

BaseClass

如果可能的话,我不想每次都创建虚拟课程。

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

我同意其他评论,这不应该是生产代码,但是当然可以完成它的乐趣:

public static T CreateAbstractInstance<T>() where T : class =>
    (T)Activator.CreateInstance(
        Thread.GetDomain()
                .DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run)
                .DefineDynamicModule("DynamicModule")
                .DefineType("DynamicType", TypeAttributes.Public | TypeAttributes.Class, typeof(T))
                .CreateType());

private static TResult AbstractInvoke<TClass, TResult>(string methodName) where TClass : class
{
    var method = typeof(TClass).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

    var elegate = method.CreateDelegate(typeof(Func<BaseClass, TResult>));

    return (TResult)elegate.DynamicInvoke(CreateAbstractInstance<TClass>());
}

private static void Main()
{
    var result = AbstractInvoke<BaseClass, int>("getValue");

    Console.WriteLine(result);
}

可能有一些方法欺骗编译器并在没有创建实例的情况下调用它,但是我得到了太多的 Visual Studio 崩溃来继续调查其他方法。表达似乎在一天结束时无处可去,它仍然必须生成有效的代码,因此无法将表达式欺骗为无效的lambda。

如果您重用CreateAbstractInstance中的单例实例,则在创建第一个对象后不应该有开销(如果您调用非公共方法,则不包括反射用法)。

我想我也可以在答案中加上这个:

我注意到在单元测试中使用它的评论;如果你使用 Moq (可能是大多数体面的框架),你可以这样做:

var bc = new Mock<BaseClass>().Object;
// Invoke whatever you want on `bc` with reflection or not.

虽然请注意,如果方法是virtual,它将自动覆盖它,因此您不会默认获得基类逻辑,但可以解决设置模拟的问题。

答案 1 :(得分:0)

您可以尝试使用开放实例委托。试试这个:

var method = typeof(BaseClass).GetMethod("getValue");
var func = (Func<BaseClass, int>) Delegate.CreateDelegate(typeof(Func<BaseClass, int>), method);
int result = func(null);

注意:上述技术的工作原理是省略成员调用中隐藏的this参数。这仅在您的方法不需要访问实例时才有效。如果您尝试访问该实例,则会获得空引用异常。