C# 通过反射重新实例化静态构造函数

C# 通过反射重新实例化静态构造函数,c#,static,system.reflection,C#,Static,System.reflection,Im使用第三方dll进行某些操作,该类的实例是静态的,有时会崩溃。 我在想,是否有一种方法可以通过反思来重新体验课堂 我使用DotPeek检查库,它看起来像这样: public class C_SomeWrapper { private static C_SomeWrapper _instance; public C_SomeWrapper() { InitStuff(); } voi

Im使用第三方dll进行某些操作,该类的实例是静态的,有时会崩溃。 我在想,是否有一种方法可以通过反思来重新体验课堂

我使用DotPeek检查库,它看起来像这样:

public class C_SomeWrapper
    {
        private static C_SomeWrapper _instance;
        public C_SomeWrapper()
        {
            InitStuff();
        }
        void InitStuff()
        {

        }
        public void Destroy()
        {
            C_SomeWrapper._instance = (C_SomeWrapper)null;
        }
        public static C_SomeWrapper Instanse
        {
            get
            {
                if (C_SomeWrapper._instance == null)
                    C_SomeWrapper._instance = new C_SomeWrapper();
                return C_SomeWrapper._instance;
            }
        }
    }
当我提到它时,我会:

C_SomeWrapper _wrapper=C_SomeWrapper.Instanse
由于正在崩溃,我想销毁()并重新实例化构造函数。 我在想也许可以访问
\u实例
,并通过反射使其为空。 我想提到的是,just Destroy()不起作用,所以我可能需要调用构造函数并初始化stuff() 有没有关于它是否可行的问题,或者有没有其他选择


谢谢

最简单的方法是将
C\u SomeWrapper.\u instance
重置为null,然后让现有代码为您重新创建一个实例。下面的示例就是这样做的(尽管它使用了不同的类名和字段名)

我正在使用一个名为
MyPrivateClass
的类型,该类型包含一个名为
SomeField
的可空静态字段(这是我经常使用的一个类):

最后,私有字段
anObject.SomeField
为空


我不确定这对于声明为
静态的类如何工作。但是,看起来
FieldInfo.SetValue(null,null)
将适用于静态成员。因此,您不需要实例化对象(如上所示)。

尝试重新运行静态构造函数,如下所示:

void Main()
{
    var t = typeof(AmStaticHearMeRoar);
    TryIt(t,RunConstructor);
    TryIt(t,RunTypeInitializer);
    TryIt(t, RunClassConstructor);
}

static void TryIt(Type t, Action<Type> f){
    Console.WriteLine("value is:" + AmStaticHearMeRoar.State);
    AmStaticHearMeRoar.Reset();
    try{
        f(t);
        Console.WriteLine("constructor rerun, value is:" + AmStaticHearMeRoar.State);
    } catch(Exception ex){
        ex.Dump();
        Console.WriteLine("constructor rerun?, value is:" + AmStaticHearMeRoar.State);
    }
    finally{
        AmStaticHearMeRoar.Reset();
    }

}

static void RunConstructor(Type t) {
    var m = t.GetConstructor(BindingFlags.Static | BindingFlags.NonPublic, System.Type.DefaultBinder, System.Type.EmptyTypes, null);
    m.Dump();
    m.Invoke(new object[] {});
}
static void RunTypeInitializer(Type t){
    t.TypeInitializer.Invoke(BindingFlags.NonPublic | BindingFlags.Static, System.Type.DefaultBinder, new object[] {},System.Globalization.CultureInfo.DefaultThreadCurrentCulture);
}
static void RunClassConstructor(Type t) {
    // only works if it hasn't been run =(
    RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
// Define other methods and classes here

public static class AmStaticHearMeRoar
{
    static int myStaticState;
    static AmStaticHearMeRoar()
    {
        myStaticState = 3;
    }
    public static void Reset() {
        myStaticState = 0;
    }
    public static int State => myStaticState;
}
void Main()
{
var t=类型(AmStaticHearMeRoar);
TryIt(t,RunConstructor);
TryIt(t,RunTypeInitializer);
TryIt(t,RunClassConstructor);
}
静态空隙率(t型,作用f){
WriteLine(“值为:”+AmStaticHearMeRoar.State);
AmStaticHearMeRoar.Reset();
试一试{
f(t);
WriteLine(“构造函数重新运行,值为:”+AmStaticHearMeRoar.State);
}捕获(例外情况除外){
例如Dump();
WriteLine(“构造函数重新运行”,值为:“+AmStaticHearMeRoar.State”);
}
最后{
AmStaticHearMeRoar.Reset();
}
}
静态无效运行构造函数(类型t){
var m=t.GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,System.Type.DefaultBinder,System.Type.EmptyTypes,null);
m、 Dump();
m、 调用(新对象[]{});
}
静态无效RunTypeInitializer(类型t){
t、 TypeInitializer.Invoke(BindingFlags.NonPublic | BindingFlags.Static,System.Type.DefaultBinder,新对象[]{},System.Globalization.CultureInfo.DefaultThreadCurrentCulture);
}
静态void RunClassConstructor(类型t){
//只有在未运行时才有效=(
RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
//在此处定义其他方法和类
公共静态类AmStaticHearMeRoar
{
静态int myStaticState;
静态AmStaticHearMeRoar()
{
myStaticState=3;
}
公共静态无效重置(){
myStaticState=0;
}
公共静态int State=>myStaticState;
}
另见


但是2失败,第3个只知道构造函数已经运行。

“类的实例是静态的”如果我见过的话,这是一个矛盾的说法。字段和函数要么是实例,要么是静态的。它们不能两者兼而有之。有时你可能会有一个单一的实例,这可能是你真正的意思。但是有一个公共构造函数,所以它看起来不像那样。你想再次调用静态构造函数吗?这看起来像是真的很糟糕的想法;它们的编写思想是它们只被调用一次。如果您(真的)想,您可能可以将
C\u SomeWrapper.\u instance
设置为
null
(通过反射)然后,下次有人访问
C_SomeWrapper.instance
,内部实例将被重建。确保在执行此操作时,没有人试图访问与类有关的任何内容。是的,确切地说,每次崩溃时,我都要调用second、third an等,您能帮助我如何通过反射使Instanse=null吗?和from有时会崩溃。听起来您可能应该对此进行调查并找出原因。似乎您正试图在这里解决一个更大的问题。我按照您的建议进行了尝试,但对于var anObject=new MyPrivateClass();它会抛出TargetInvocationException+InnerException{“试图读取或写入受保护的内存。这通常表示其他内存已损坏。”}System.Exception{System.AccessViolationException}
void Main()
{
    var t = typeof(AmStaticHearMeRoar);
    TryIt(t,RunConstructor);
    TryIt(t,RunTypeInitializer);
    TryIt(t, RunClassConstructor);
}

static void TryIt(Type t, Action<Type> f){
    Console.WriteLine("value is:" + AmStaticHearMeRoar.State);
    AmStaticHearMeRoar.Reset();
    try{
        f(t);
        Console.WriteLine("constructor rerun, value is:" + AmStaticHearMeRoar.State);
    } catch(Exception ex){
        ex.Dump();
        Console.WriteLine("constructor rerun?, value is:" + AmStaticHearMeRoar.State);
    }
    finally{
        AmStaticHearMeRoar.Reset();
    }

}

static void RunConstructor(Type t) {
    var m = t.GetConstructor(BindingFlags.Static | BindingFlags.NonPublic, System.Type.DefaultBinder, System.Type.EmptyTypes, null);
    m.Dump();
    m.Invoke(new object[] {});
}
static void RunTypeInitializer(Type t){
    t.TypeInitializer.Invoke(BindingFlags.NonPublic | BindingFlags.Static, System.Type.DefaultBinder, new object[] {},System.Globalization.CultureInfo.DefaultThreadCurrentCulture);
}
static void RunClassConstructor(Type t) {
    // only works if it hasn't been run =(
    RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
// Define other methods and classes here

public static class AmStaticHearMeRoar
{
    static int myStaticState;
    static AmStaticHearMeRoar()
    {
        myStaticState = 3;
    }
    public static void Reset() {
        myStaticState = 0;
    }
    public static int State => myStaticState;
}