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
如果可能的话,我不想每次都创建虚拟课程。
有更好的方法吗?
答案 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
参数。这仅在您的方法不需要访问实例时才有效。如果您尝试访问该实例,则会获得空引用异常。