C# 通过反射重新实例化静态构造函数
Im使用第三方dll进行某些操作,该类的实例是静态的,有时会崩溃。 我在想,是否有一种方法可以通过反思来重新体验课堂 我使用DotPeek检查库,它看起来像这样: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
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;
}