Context
I have an InteractionWindowPresenter class in charge of creating Windows. Some of them may be modal and I want to keep a counter of the number of opened modal windows in order to notify other parts of the application.
Therefore I added a _modalsCount variable to the class, updated whenever a modal window is opened or closed:
public class InteractionWindowPresenter<TWindow, TNotification>
where TWindow : System.Windows.Window
where TNotification : Prism.Interactivity.InteractionRequest.INotification
{
private static int _modalsCount = 0;
...
private bool _useModalWindow;
public InteractionWindowPresenter(InteractionRequest<TNotification> request,
bool useModalWindow = false)
{
_useModalWindow = useModalWindow;
}
public void Show()
{
var window = ...
window.Closed += (s, e) =>
{
if (_useModalWindow)
{
_modalsCount = Math.Max(0, --_modalsCount);
if (_modalsCount == 0)
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(false);
}
};
if (_useModalWindow)
{
_modalsCount++;
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(true);
window.ShowDialog();
}
else
window.Show();
}
}
Upon initialization, each Prism module - ie. each class implementing IModule - instantiates an InteractionWindowPresenter per view that must be shown on a Window and holds a reference to it. For instance:
[ModuleExport("ClientsModule", typeof(Module),
DependsOnModuleNames = new[] { "RibbonModule", "ClientsModelModule" },
InitializationMode = InitializationMode.WhenAvailable)]
public class Module : IModule
{
InteractionWindowPresenter<ClientSelectionWindow, ClientSelection> _selectionPresenter;
public void Initialize()
{
_selectionPresenter =
new InteractionWindowPresenter<ClientSelectionWindow, ClientSelection>
(Interactions.ClientSelectionRequest, useModalWindow: true);
}
}
The InteractionWindowPresenter class is defined in an infrastructure assembly directly referenced by all the modules as well as other infrastructure assemblies. It is not referenced by the launcher application, which is merely a MefBootstrapper. Hence, MEF is used for composition.
The problem
Setting a breakpoint on the _modalsCount initialization line reveals that it is not executed when the InteractionWindowPresenter instances are created. Instead, it is executed the first time (and only that time) the variable is used in each module - ie. the first time the Show method is called from each module. Thus, each module has its own value, shared across all the instances of that specific module.
I understand that the lazy evaluation is due to the curious nature of beforefieldinit. However I expected that evaluation to happen just once for the whole application instead of per module.
I also tried performing the initialization in the static constructor:
static int _modalsCount;
static InteractionWindowPresenter()
{
_modalsCount = 0;
}
In this case, the static constructor is invoked prior to the execution of the instance constructor, but every single time an instance is created. Therefore, the variable seems not to be static anymore.
From my understanding, static variables are initialized once per AppDomain. Thus, since all my assemblies (modules and infrastructure) are in the same AppDomain, this should not happen. Am I wrong in any of these two assumptions?
Work-around employed so far
Creating a simple class to hold the counter avoids this problem:
static class ModalsCounter
{
private static int _modalsCount = 0;
public static int Increment()
{
return ++_modalsCount;
}
public static int Decrement()
{
_modalsCount = Math.Max(0, --_modalsCount);
return _modalsCount;
}
}
Thus replacing the calls to _modalsCount by:
ModalsCounter.Increment();
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(true);
and:
if (_useModalWindow && ModalsCounter.Decrement() == 0)
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(false);
So what am I missing here? Have I somehow misunderstood the lifecycle and scope of static variables or are Prism modules and/or MEF messing with me?
The static is created once for each Type. Since you are using a Generic Type the number of Types created will be equivalent to the number of combinations of Type variables you use in the initializer. This is why hiding the static inside a non generic class works (probably a better pattern anyhow).
You class is generic, and each constructed generic type (with type arguments specified) is a separate type. Each of them has its own set of static members.
From C# language specification, section 4.4.2 Open and closed types:
Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Since an open type does not exist at run-time, there are no static variables associated with an open type.
You can make a simple test:
public class Test<T>
{
public static object obj = new object();
}
Console.WriteLine(object.ReferenceEquals(Test<string>.obj, Test<object>.obj)); // false
Your workaround (keeping the static counter in a non-generic class) is correct.
Related
I'm trying to use the AutoMapper for model-viewmodel mapping and wanted to have the mapping configuration executed once in the static constructor of the type. The static constructor of a type is not invoked when Mapper.Map (AutoMapper) is invoked with that type.
My understanding is that the Mapper.Map would try to access the type, its members through reflection and on the first attempt of the usage the static constructor would be called. This is something basic but challenges my understanding. The code snippet is provided.
class SampleViewModel
{
static SampleViewModel()
{
Mapper.Initialize(cfg => cfg.CreateMap<Sample, SampleViewModel>().ReverseMap());
}
public SampleViewModel()
{
}
public int PropertyA { get; set; }
public int PropertyB { get; set; }
}
Sample s = new Sample { PropertyA = 10, PropertyB = 20 };
var obj = Mapper.Map<SampleViewModel>(s); // fails
Isn't the static constructor called (if provided) when the type and members are accessed through reflection for the first time?
You're not accessing any members of SampleViewModel - it's not enough to just reference the type itself.
Mapper.Map only accesses its own internal "dictionary" of mappings - before it could ever get to a point where it deals with a SampleViewModel, it fails. The static constructor never runs, so it cannot add "itself" into the Mapper.
Now, if this didn't involve reflection, you would be right that the static constructor would be called - simply because it would happen during the compilation of the method containing the access, e.g.:
var obj = Mapper.Map<SampleViewModel>(s);
Console.WriteLine(obj.SomeField);
In this case, since the method is referencing a field on SampleViewModel, the static constructor for SampleViewModel will be invoked during JIT compilation of the containing method, and as such, the Mapper.Map<SampleViewModel>(s) line will execute correctly, since the mapping is now present. Needless to say this is not the proper solution to your problem. It would just make the code absolutely horrible to maintain :)
DISCLAIMER: Even though this might fix the problem right now, it depends on a non-contractual behaviour in the current implementation of MS.NET on Windows. The contract specifies that the type initializer is invoked before any access to a member of the type, but that still means that a valid implementation of CIL might only call the type initializer after Mapper.Map, as long as it happens before obj.SomeField - and even then, it might be that obj.SomeField gets optimized away if the compiler can ensure it is safe to do so. The only real way to enforce the call of the type initializer is to call RuntimeHelpers.RunClassConstructor, but by that point, you could just as well add a static Init method or something.
The real problem is that you shouldn't really initialize stuff like this in a static constructor in the first place. Mappings should be set in some kind of deterministic initialization process, say, an explicitly invoked InitMappings method. Otherwise you're opening yourself to a huge can of Heisenbugs, not to mention subtle changes in the CLR breaking your whole application for no apparent reason.
Static constructors just aren't meant for "registration", just the initialization of the type itself - anything else is an abuse, and will cause you (or the .NET compatibility team) trouble.
Static constructors run at an implementation-defined time just before the first instance of that class is created, or before any static member of that type is accessed. See When is a static constructor called in C#?.
The mapper tries to find a mapping before doing its work of instantiating the class to map into, and thus can't find a mapping, because the class was never instantiated before that moment.
Just move your mapping initialization code into a AutoMapperBootstrap.cs file or something, and call that in your application initialization.
".. The static constructor of a type is not invoked when Mapper.Map (AutoMapper) is invoked with that type..."
I tested your scenario and observed that the static constructor is indeed being called before the first instance of the object is created.
C# Programming Guide: Static Constructors
I also went ahead and modified the sample code by adding a GetMapper function which returns an IMapper. This might seem like an overkill for day-to-day simple mapping, but if we need an object to give us its mapper, perhaps we can get it from a static method.
One can easily move the responsibility of creating the Mapper object to a factory or a DI container which, for the sake of simplicity, I did not include here.
Worth noting that in this example, the static fields are initialized before the static constructor which is called right after the static read-only fields are initialized.
Uses AutoMapper v12.0 and .Net Core 3.1.
public class SimpleObjectToMap
{
private static readonly MapperConfiguration _simpleObjMapperConfig = new MapperConfiguration(
config => config.CreateMap<SimpleObjectToMap, ObjectToBeMappedTo>());
private static readonly IMapper _mapper = new Mapper(_simpleObjMapperConfig);
private int _propertyA;
public int PropertyA
{
get
{
Console.WriteLine("ObjectToMap.PropertyA.Get");
return _propertyA;
}
set { _propertyA = value; }
}
static SimpleObjectToMap()
{
Console.WriteLine("*** ObjectToMap static ctor called ***");
}
public static IMapper GetMapper()
{
return _mapper;
}
}
public class ObjectToBeMappedTo
{
static ObjectToBeMappedTo()
{
Console.WriteLine("*** ObjectToBeMappedTo static ctor called ***");
}
private int _propertyA;
public int PropertyA
{
get { return _propertyA; }
set
{
Console.WriteLine("ObjectToBeMappedTo.PropertyA.Set");
_propertyA = value;
}
}
}
public class TestObjectMappingWithStaticCtor
{
public void TestWithStaticCtor()
{
SimpleObjectToMap objToMap = new SimpleObjectToMap { PropertyA = 27 };
var mappedObject = SimpleObjectToMap.GetMapper().Map<ObjectToBeMappedTo>(objToMap);
}
}
I have searched about static variables in C#, but I am still not getting what its use is. Also, if I try to declare the variable inside the method it will not give me the permission to do this. Why?
I have seen some examples about the static variables. I've seen that we don't need to create an instance of the class to access the variable, but that is not enough to understand what its use is and when to use it.
Second thing
class Book
{
public static int myInt = 0;
}
public class Exercise
{
static void Main()
{
Book book = new Book();
Console.WriteLine(book.myInt); // Shows error. Why does it show me error?
// Can't I access the static variable
// by making the instance of a class?
Console.ReadKey();
}
}
A static variable shares the value of it among all instances of the class.
Example without declaring it static:
public class Variable
{
public int i = 5;
public void test()
{
i = i + 5;
Console.WriteLine(i);
}
}
public class Exercise
{
static void Main()
{
Variable var1 = new Variable();
var1.test();
Variable var2 = new Variable();
var2.test();
Console.ReadKey();
}
}
Explanation: If you look at the above example, I just declare the int variable. When I run this code the output will be 10 and 10. Its simple.
Now let's look at the static variable here; I am declaring the variable as a static.
Example with static variable:
public class Variable
{
public static int i = 5;
public void test()
{
i = i + 5;
Console.WriteLine(i);
}
}
public class Exercise
{
static void Main()
{
Variable var1 = new Variable();
var1.test();
Variable var2 = new Variable();
var2.test();
Console.ReadKey();
}
}
Now when I run above code, the output will be 10 and 15. So the static variable value is shared among all instances of that class.
C# doesn't support static local variables (that is, variables that are declared in method scope).
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members#static-members
You can declare static fields (class members) though.
Reasoning: Static field is a state, shared with all instances of particular type. Hence, the scope of the static field is entire type. That's why you can't declare static instance variable (within a method) - method is a scope itself, and items declared in a method must be inaccessible over the method's border.
static variables are used when only one copy of the variable is required. so if you declare variable inside the method there is no use of such variable it's become local to function only..
example of static is
class myclass
{
public static int a = 0;
}
Variables declared static are commonly shared across all instances of a class.
Variables declared static are commonly shared across all instances of a class. When you create multiple instances of VariableTest class This variable permanent is shared across all of them. Thus, at any given point of time, there will be only one string value contained in the permanent variable.
Since there is only one copy of the variable available for all instances, the code this.permament will result in compilation errors because it can be recalled that this.variablename refers to the instance variable name. Thus, static variables are to be accessed directly, as indicated in the code.
Some "real world" examples for static variables:
building a class where you can reach hardcoded values for your application. Similar to an enumeration, but with more flexibility on the datatype.
public static class Enemies
{
public readonly static Guid Orc = new Guid("{937C145C-D432-4DE2-A08D-6AC6E7F2732C}");
}
The widely known singleton, this allows to control to have exactly one instance of a class. This is very useful if you want access to it in your whole application, but not pass it to every class just to allow this class to use it.
public sealed class TextureManager
{
private TextureManager() {}
public string LoadTexture(string aPath);
private static TextureManager sInstance = new TextureManager();
public static TextureManager Instance
{
get { return sInstance; }
}
}
and this is how you would call the texturemanager
TextureManager.Instance.LoadTexture("myImage.png");
About your last question:
You are refering to compiler error CS0176. I tried to find more infor about that, but could only find what the msdn had to say about it:
A static method, field, property, or event is callable on a class even
when no instance of the class has been created. If any instances of
the class are created, they cannot be used to access the static
member. Only one copy of static fields and events exists, and static
methods and properties can only access static fields and static
events.
Static variables are used when only one copy of it is required. Let me explain this with an example:
class circle
{
public float _PI =3.14F;
public int Radius;
public funtionArea(int radius)
{
return this.radius * this._PI
}
}
class program
{
public static void main()
{
Circle c1 = new Cirle();
float area1 = c1.functionRaduis(5);
Circle c2 = new Cirle();
float area2 = c1.functionRaduis(6);
}
}
Now here we have created 2 instances for our class circle , i.e 2 sets of copies of _PI along with other variables are created. So say if we have lots of instances of this class multiple copies of _PI will be created occupying memory. So in such cases it is better to make such variables like _PI static and operate on them.
class circle
{
static float _PI =3.14F;
public int Radius;
public funtionArea(int radius)
{
return this.radius * Circle._PI
}
}
class program
{
public static void main()
{
Circle c1 = new Cirle();
float area1 = c1.functionRaduis(5);
Circle c2 = new Cirle();
float area2 = c1.functionRaduis(6);
}
}
Now no matter how many instances are made for the class circle , only one copy exists of variable _PI saving our memory.
Static classes don't require you to create an object of that class/instantiate them, you can prefix the C# keyword static in front of the class name, to make it static.
Remember: we're not instantiating the Console class, String class, Array Class.
class Book
{
public static int myInt = 0;
}
public class Exercise
{
static void Main()
{
Book book = new Book();
//Use the class name directly to call the property myInt,
//don't use the object to access the value of property myInt
Console.WriteLine(Book.myInt);
Console.ReadKey();
}
}
The data members and function members that operate on the instance of the type
are called instance members. The int’s ToString method (for example) are examples of instance members. By default, members are instance members.
Data members and function members that don’t operate on the instance of the type, but rather on the type itself, must be marked as static. The Test.Main and Console.WriteLine methods are static methods. The Console class is actually a static class, which means all its members are static. You never actually create instances of a Console—one console is shared across the whole application.
In response to the "when to use it?" question:
I often use a static (class) variable to assign a unique instance ID to every instance of a class. I use the same code in every class, it is very simple:
//Instance ID ----------------------------------------
// Class variable holding the last assigned IID
private static int xID = 0;
// Lock to make threadsafe (can omit if single-threaded)
private static object xIDLock = new object();
// Private class method to return the next unique IID
// - accessible only to instances of the class
private static int NextIID()
{
lock (xIDLock) { return ++xID; }
}
// Public class method to report the last IID used
// (i.e. the number of instances created)
public static int LastIID() { return xID; }
// Instance readonly property containing the unique instance ID
public readonly int IID = NextIID();
//-----------------------------------------------------
This illustrates a couple of points about static variables and methods:
Static variables and methods are associated with the class, not any specific instance of the class.
A static method can be called in the constructor of an instance - in this case, the static method NextIID is used to initialize the readonly property IID, which is the unique ID for this instance.
I find this useful because I develop applications in which swarms of objects are used and it is good to be able to track how many have been created, and to track/query individual instances.
I also use class variables to track things like totals and averages of properties of the instances which can be reported in real time. I think the class is a good place to keep summary information about all the instances of the class.
Try calling it directly with class name Book.myInt
On comparison with session variables, static variables will have same value for all users considering i am using an application that is deployed in server. If two users accessing the same page of an application then the static variable will hold the latest value and the same value will be supplied to both the users unlike session variables that is different for each user. So, if you want something common and same for all users including the values that are supposed to be used along the application code then only use static.
You don't need to instantiate an object, because yau are going to use
a static variable:
Console.WriteLine(Book.myInt);
Static variable retains it's previous value until the program exit. Static is used by calling directly class_Name.Method() or class_Name.Property. No object reference is needed. The most popular use of static is C#'s Math class.
Math.Sin(), Math.Cos(), Math.Sqrt().
I want to programmatically determine the space I've got for some controls I want to create dynamically. So, I want to get the container's height and divide it by the number of rows (a constant).
I've got this function (this code is part of the form on which the panel named dynamicPanel lives):
private static int getControlHeightToUse() {
return (dynamicPanel.Height / NUMBER_OF_ROWS);
}
...which gives me the compile-time error, "*An object reference is required for the non-static field, method, or property RememberNextGen_CRLogins.CRLoginsMainForm.dynamicPanel'*"
I don't understand what it's trying to tell me/what it wants.
If I remove the "static":
private int getControlHeightToUse() {
return (dynamicPanel.Height / NUMBER_OF_ROWS);
}
...I then get the compile-time error, "*A field initializer cannot reference the non-static field, method, or property 'TitanNextGen_CRLogins.CRLoginsMainForm.getControlHeightToUse()'*"
...on the indicated line below:
public partial class CRLoginsMainForm : Form {
int controlHeight = getControlHeightToUse(); // <-- err
A static method has only direct access to static memebers of the class, if you want to use instance members of the class, you must pass in an instance of the class to the method (or have one available as a static as in the case of a singleton).
Thus, you can modify your method to take in the instance member that is preventing it from being able to be static:
private static int getControlHeightToUse(Panel thePanel)
{
return (thePanel.Height / NUMBER_OF_ROWS);
}
Then just pass in dynamicPanel on the call...
Instance methods, however, can access static members. Remember that static members are shared among all instances and exist even if no instance of the class exist. Thus they can't call instance members since they don't know which instance you are talking about.
pass dynamicPanel as parameter to static method
public partial class CRLoginsMainForm : Form {
int controlHeight = getControlHeightToUse(dynamicPanel);
change getControlHeightToUse as below
private static int getControlHeightToUse(Panel panel) {
return (panel.Height / NUMBER_OF_ROWS);
}
if you want to call non static method from static method you can do as below
public class Foo
{
// public method
public void Method1()
{
}
public static void Data2()
{
// call public method from static method
new Foo().Method1();
}
}
Hello I have this code here:
Memory.OpenProcess(Processes[0].Id);
Hook.Apply(........);
Memory and Hook are both non-static classes, and openprocess and Apply are both static methods within those classes.
However, the problem is, for each instance of my Memory or Hook, I want to have a different process opened, and a different Hook applied.
What I want to do is:
Memory newMemory = new Memory();
newMemory.OpenProcess(processes[1].Id);
Hook newHook = new Hook();
newHook.Apply(....);
But of course I cannot do this because the methods are static and not particular to each instance.
I cannot change the static methods because these methods are coming from a dll in which I do not have access to the source code.
Any ideas?
**Edit: I want to do this so I can avoid having to rehook the process every time a new thread comes along that is working with a different process.
It seems that you cannot do that by design. The implementor of the classes from the dll you are consuming might have explicitly want to avoid the functionality you are trying to achieve.
You can load each thread in different AppDomain, that would give you different static methods.
Also, ThreadStaticAttribute might be helpful for you. Don't sure if it fits you, but give it a look.
Upd: More info about using AppDomains. Lets assume, that you have 3-rd party class Memory defined as follows. (And you cannot change it, and it uses inner static variables)
// Cannot be changed
public class Memory
{
static int StaticId;
public static void OpenProcess(int id)
{
StaticId = id;
}
public static int GetOpenedId()
{
return StaticId;
}
}
You can write a wrapper, deriving from MarshalByRefObject (that's important):
class MemoryWrap : MarshalByRefObject
{
public void OpenProcess(int id)
{
Memory.OpenProcess(id);
}
public int GetOpenedId()
{
return Memory.GetOpenedId();
}
}
So if you create instances of MemoryWrap not by new keyword, but using AppDomain.CreateInstanceAndUnwrap in another domain, each instance would have it's own static contexts. Example:
class Program
{
static void Main(string[] args)
{
var type = typeof(MemoryWrap);
var domain1 = AppDomain.CreateDomain("Domain 1");
var memory1 = (MemoryWrap)domain1.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
var domain2 = AppDomain.CreateDomain("Domain 2");
var memory2 = (MemoryWrap)domain2.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
memory1.OpenProcess(1);
memory2.OpenProcess(2);
Console.WriteLine(memory1.GetOpenedId());
Console.WriteLine(memory2.GetOpenedId());
Console.ReadLine();
}
}
It would print:
1
2
PS: in that example I didn't do the clean up just for readability (unloading domains with AppDomain.Unload() and other things). Don't forget to do it in you code. + There is some mess with lifetime of objects in another domain, but it is next level of problems)))
I'm not sure I fully understand the question, but I will try to answer anyways.
You could define two new classes:
public class MemoryInstance : Memory
{
private var m_instanceProcessId;
public MemoryInstance(var processId) : base()
{
m_instanceProcessId = processId;
}
public void OpenProcess()
{
Memory.OpenProcess(m_instanceProcessId);
}
}
public class HookInstance: Hook
{
private var m_hookId;
public HookInstance(var hookId) : base()
{
m_hookId = hookId;
}
public void Apply()
{
Hook.Apply(m_hookId);
}
}
Then in your code you could call:
public static void Main(String[] args)
{
MemoryInstance newMemory = new MemoryInstance(processes[1].Id);
HookInstance newHook = new HookInstance(hookId);
newMemory.OpenProcess();
newHook.Apply();
}
See , if the API writers are doing that it must be for some reason , you should consult your API writers for he reason or if they can provide you something at instamnce level.
BUT for circumvent your situation , you can use the method provided The_Smallest above.
or you can make use of Reflection as shown below
Memory m = Activator.CreateInstance("Your Dll Name", true) , here true stands for the calling of private constructor.
But i am not convinced , you should do it , you first call to the API writer to get the reason of doing this.
I am using .net 1.1. I have a session class in which I have stored many static variables that hold some data to be used by many classes.
I want to find a simple way of destroying this class instead of resetting every variable one by one. For example if there is a static class MyStatic, I would have liked to destroy/remove this class from the memory by writing MyStatic = null, which is not currently possible,
Additional question.
The idea of singleton is good, but I have the following questions:
If singleton is implemented, the 'single' object will still remain in the memory. In singleton, we are only checking if an instance is already existing. how can i make sure that this instance variable also gets destroyed.
I have a main class which initializes the variable in the static class. Even if I plan to implement a Rest() method, I need to call it from a method, for eg, the destructor in the main class. But this destructor gets called only when GC collects this main class object in the memory, which means the Reset() gets called very late
thanks
pradeep
Don't use a static class to store your variables. Use an instance (and make it a singleton if you only want one instance at any given time.) You can then implement IDisposible, and just call Dispose() when you want to destroy it.
For more information check out this site: http://csharpindepth.com/Articles/General/Singleton.aspx
EDIT
The object is still subject to garbage collection, so unless you are using lots of unmanaged resources, you should be fine. You can implement IDisposible to clean up any resources that need to be cleaned up as well.
Instead of a static class, have a static instance of a class:
class Foo
{
public int Something;
public static Foo Instance = new Foo();
public void Reset()
{
Instance = new Foo();
}
}
void test
{
int i = Foo.Instance.Something;
}
You can also delegate to an instance of the class:
class Foo
{
public int Something
{
get { return instance.something; }
}
private int something;
private static Foo instance = new Foo();
public void Reset()
{
instance = new Foo();
}
}
void test
{
int i = Foo.Something;
}
There's no way to destroy a static unless it resides in a separate AppDomain in which case you can get rid of it by unloading the AppDomain. However it is usually better to avoid statics.
EDIT: Additional question
When the singleton is no longer referenced it will be collected just as everything else. In other words, if you want it collected you must make sure that there are no references to it. It goes without saying that if you store a static reference to your singleton, you will have the same problem as before.
Use a Singleton like ktrauberman said, and have an initialization method or a reset method. You only have to write the code once and call the method.
You destroy objects, not classes. There's nothing wrong with static classes--C# provides them for a reason. Singletons are just extra overhead, unless you actually need an object, e.g. when you have to pass the object as a parameter.
Static classes contain only static variables. These variables tend to last for the lifetime of the app, in which case you don't have to worry about disposing referenced objects, unless you have a mild case of OCD. That just leaves the case where your static class allocates and releases resources throughout its lifetime. Dispose of these objects in due course as you usually would (e.g., "using...").
The best way in your condition is to have an Reset() method built-in as well, which can reset the values of the class.
class myclass
{
private static myclass singleobj = null;
private myclass(){}
public static myclass CreateInstance()
{
if(singleobj == null)
singleobj = new myclass();
return singleobj
}
}
Building on Ahemd Said's answer: (and props to him!)
class Singleton
{
private static Singleton instance = null;
private Singleton(){} // private constructor: stops others from using
public static Singleton Instance
{
get { return instance ?? (instance = new Singleton()); }
set {
if (null != value)
{ throw new InvalidValueException(); }
else
{ instance = null; }
}
}
}
void SampleUsage()
{
Singleton myObj = Singleton.Instance;
// use myObj for your work...
myObj.Instance = null; // The set-operator makes it ready for GC
}
(untested... but mostly right, I think)
You could also add in usage of the IDispose interface for more cleanup.
You can create a method in the static class which resets the values of all properties.
Consider you have a static class
public static class ClassA
{
public static int id=0;
public static string name="";
public static void ResetValues()
{
// Here you want to reset to the old initialized value
id=0;
name="";
}
}
Now you can use any of the below approaches from any other class to reset value of a static class
Approach 1 - Calling directly
ClassA.ResetValues();
Approach 2 - Invoking method dynamically from a known namespace and known class
Type t1 = Type.GetType("Namespace1.ClassA");
MethodInfo methodInfo1 = t1.GetMethod("ResetValues");
if (methodInfo1 != null)
{
object result = null;
result = methodInfo1.Invoke(null, null);
}
Approach 3 - Invoking method dynamically from an assembly/set of assemblies
foreach (var Ass in AppDomain.CurrentDomain.GetAssemblies())
{
// Use the above "If" condition if you want to filter from only one Dll
if (Ass.ManifestModule.FullyQualifiedName.EndsWith("YourDll.dll"))
{
List<Type> lstClasses = Ass.GetTypes().Where(t => t.IsClass && t.IsSealed && t.IsAbstract).ToList();
foreach (Type type in lstClasses)
{
MethodInfo methodInfo = type.GetMethod("ResetValues");
if (methodInfo != null)
{
object result = null;
result = methodInfo.Invoke(null, null);
}
}
break;
}
}
Inject the objects into the static class at startup from a non static class that implements IDisposable, then when your non static class is destroyed so are the objects the static class uses.
Make sure to implement something like "Disable()" so the static class is made aware it's objects have just been set to null.
Eg I have a logger class as follows:
public static class Logger
{
private static Action<string, Exception, bool> _logError;
public static void InitLogger(Action<string, Exception, bool> logError)
{
if(logError != null) _logError = logError;
}
public static void LogError(string msg, Exception e = null, bool sendEmailReport = false)
{
_logError?.Invoke(msg, e, sendEmailReport);
}
In my constructor of my Form I call the following to setup the logger.
Logger.InitLogger(LogError);
Then from any class in my project I can do the following:
Logger.LogError("error",new Exception("error), true);