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

时间:2018-10-25 19:21:43

标签: c# static system.reflection

我正在使用第三方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

由于崩溃,我想Destroy()并重新实例化构造函数。 我当时认为可以访问_instance并通过反射使其为空。 我想提一下,仅Destroy()不起作用,所以可能我需要调用构造函数并调用InitStuff() 关于是否可行或可能有其他选择的任何疑惑

谢谢

2 个答案:

答案 0 :(得分:1)

最简单的方法是将C_SomeWrapper._instance重设为null,然后让现有代码为您重新创建实例。下面的示例做到了这一点(尽管它使用了不同的类名和字段名)。

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

   var myType = typeof(MyPrivateClass);
   var anObject = new MyPrivateClass();

   var myField = myType.GetField("SomeField", BindingFlags.Static | BindingFlags.NonPublic);
   myField.SetValue(anObject, null);

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

我不确定这对于声明为static的类如何工作。但是,看来FieldInfo.SetValue(null, null)适用于静态成员。结果,您无需实例化anObject(如上所示)。

答案 1 :(得分:0)

尝试像这样重新运行静态构造函数:

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

另请参阅How do I invoke a static constructor with reflection?

无论2失败了,第3个都知道构造函数已经运行。