Reputation: 621
Im using a 3rd party dll for some operations, the instance of the class is static and from time to time is crashing. I was thinking if there is a way to reinstantiate the class via Reflection.
I used DotPeek to check the library and it looks something like this:
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;
}
}
}
When i reference to it i do :
C_SomeWrapper _wrapper=C_SomeWrapper.Instanse
Since is crashing i would like to Destroy() and re-instantiate the constructor.
I was thinking maybe is posible to acces _instance
and make it null via Reflection.
Id like to mention that just Destroy() doesnt work so probably i need to call the constructor and to InitStuff()
Any toughts on if its posible or not or maybe some alternatives
Thanks
Upvotes: 1
Views: 200
Reputation: 7111
The easiest way to do this would be to reset C_SomeWrapper._instance
back to null and then let the existing code recreate an instance for you. The example below does this (though it uses a different class name and field name).
I'm working with a type called MyPrivateClass
that contains a nullable static field named SomeField
(it's a class I had hanging around):
var myType = typeof(MyPrivateClass);
var anObject = new MyPrivateClass();
var myField = myType.GetField("SomeField", BindingFlags.Static | BindingFlags.NonPublic);
myField.SetValue(anObject, null);
At the end of that, the private field anObject.SomeField
is null.
I wasn't sure how this might work for a class that is declared static
. However, it looks like FieldInfo.SetValue(null, null)
will work for a static member. As a result, you don't need to instantiate anObject
(as shown above).
Upvotes: 1
Reputation: 18746
Attempt to Re-run a static constructor like so:
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;
}
see also How do I invoke a static constructor with reflection?
however 2 fail, the 3rd just knows the constructor was already run.
Upvotes: 0