这可以满足您的目的,尽管我当然会包括一些异常处理,并在其实现中附带大量关于其工作原理和方式的文档。
当Base
运行(一次)的静态构造函数时,当前加载到应用程序域中的所有程序集都会被编目,选择从Base
. 遍历这些,我们运行静态构造函数。值得注意的是,这不再保证每个实现的 cctor 将只运行一次,必须将逻辑添加到每个实现中以重新做出该断言。此外,在 cctor forBase
运行后加载的类型不会通过调用Base
要模拟虚方法,请使用new
关键字隐藏基方法。您可以通过使用声明类的名称对其进行限定来调用基方法(如B
示例中的类)
using System;
using System.Linq;
using System.Runtime.CompilerServices;
namespace ConsoleApplication6
{
public class Base
{
static Base()
{
Console.WriteLine("Base cctor");
var thisType = typeof (Base);
var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes());
var derivations = loadedTypes.Where(thisType.IsAssignableFrom);
foreach(var derivation in derivations)
{
RuntimeHelpers.RunClassConstructor(derivation.TypeHandle);
}
}
public static void Foo()
{
Console.WriteLine("Bar");
}
}
public class A : Base
{
static A()
{
Console.WriteLine("A cctor");
}
}
public class B : Base
{
static B()
{
Console.WriteLine("B cctor");
}
public new static void Foo()
{
Console.WriteLine("Bar!!");
Base.Foo();
}
}
class Program
{
static void Main()
{
Console.WriteLine("A:");
A.Foo();
Console.WriteLine();
Console.WriteLine("B:");
B.Foo();
Console.WriteLine();
Console.WriteLine("Base:");
Base.Foo();
Console.ReadLine();
}
}
}
编辑
另一种选择在于 CRTP(或 C# 范例中的 CRGP)或奇怪的重复模板(通用)参数模式
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication6
{
public class Base<T>
where T : Base<T>
{
static Base()
{
RuntimeHelpers.RunClassConstructor(typeof (T).TypeHandle);
}
public static void Foo()
{
Console.WriteLine("Bar");
}
}
public class Base : Base<Base>
{
}
public class A : Base<A>
{
static A()
{
Console.WriteLine("A cctor");
}
}
public class B : Base<B>
{
static B()
{
Console.WriteLine("B cctor");
}
public new static void Foo()
{
Console.WriteLine("Bar!!");
Base<B>.Foo();
}
}
class Program
{
static void Main()
{
Console.WriteLine("A:");
A.Foo();
Console.WriteLine();
Console.WriteLine("B:");
B.Foo();
Console.WriteLine();
Console.WriteLine("Base:");
Base.Foo();
Console.ReadLine();
}
}
}
在这种情况下,当我们调用一个静态方法时,A
我们实际上调用的Base<A>
是不同的方法Base<B>
,Base
因此我们实际上可以确定该方法是如何被调用的并运行适当的 cctor。