I am trying to make a singleton to account all the controllers I am going to create. When I run the website I get the stackoverflow error.
This is my singleton class:
public class MainController
{
private DatabaseController databaseController;
private UserDBController userDBController;
private static MainController MCinstance = null;
public MainController()
{
if (MCinstance == null)
{
databaseController = new DatabaseController();
userDBController = new UserDBController();
}
}
public static MainController Instance
{
get
{
if (MCinstance == null)
{
MCinstance = new MainController();
}
return MCinstance;
}
}
public UserDBController GetUserDBController()
{
return userDBController;
}
public DatabaseController GetDBController()
{
return databaseController;
}
}
This is how I use the singleton class in a different class:
private UserDBController userDBController = MainController.Instance.GetUserDBController();
What am I doing wrong?
You can change your implemention like below,
public class MainController
{
private DatabaseController databaseController;
private UserDBController userDBController;
private static MainController MCinstance = null;
static MainController()
{
MCinstance = new MainController();
MCinstance.databaseController = new DatabaseController();
MCinstance.userDBController = new UserDBController();
}
public static MainController Instance
{
get
{
return MCinstance;
}
}
public UserDBController GetUserDBController()
{
return userDBController;
}
public DatabaseController GetDBController()
{
return databaseController;
}
}
You should add the readonly modifier to your MCinstance declaration and instantiate it only once in static constructor.
public class MainController
{
public static readonly MainController Instance = null;
static MainController()
{
Instance = new MainController()
}
}
For singleton use need to use private constructor. And move code of private construct in the place where instance is creating.
public class MainController
{
private DatabaseController databaseController = new DatabaseController();
private UserDBController userDBController = new UserDBController();
private static MainController MCinstance = null;
private MainController()
{
}
public static MainController Instance
{
get
{
if (MCinstance == null)
{
MCinstance = new MainController();
}
return MCinstance;
}
}
public UserDBController GetUserDBController()
{
return userDBController;
}
public DatabaseController GetDBController()
{
return databaseController;
}
}
Essentially, this is the only code you need by making use of static classes in C#. The constructor is not public, since it is automatically called the first time you use this class. This class only has one instance.
public static class MainController
{
private static DatabaseController databaseController;
private static UserDBController userDBController;
static MainController()
{
databaseController = new DatabaseController();
userDBController = new UserDBController();
}
public static UserDBController GetUserDBController()
{
return userDBController;
}
public static DatabaseController GetDBController()
{
return databaseController;
}
}
Related
I have some kind of MonoBehaviour pool:
public class MonoPool<T> where T : MonoBehaviour
{
public List<T> PrefabPool { get; }
public MonoPool() {
PrefabPool = new List<T>();
}
public void AddObject(T prefab)
{
PrefabPool.Add(prefab);
}
}
And I want that all generators of ILevelGenerator interface returns MonoPool on Create()
public interface ILevelGenerator
{
public MonoPool<MonoBehaviour> Create();
public void Update();
public void SetMode(int mode);
}
For example I have a BuildingsGenerator and it implements this ILevelGenerator
public class BuildingsGenerator : ILevelGenerator
{
private readonly MonoPool<ModularBuilding> _buildingsPool;
public BuildingsGenerator() {
_buildingsPool = new MonoPool<ModularBuilding>();
}
public MonoPool<MonoBehaviour> Create()
{
//Logic...
//Logic...
return _buildingsPool;
}
}
BuildingsGenerator implement MonoPool as MonoPool there ModularBuilding is MonoBeh
public class ModularBuilding : MonoBehaviour
{
[SerializeField] private BuildingFloor _groundFloorElement;
[SerializeField] private BuildingFloor _middleFloorElement;
[SerializeField] private BuildingFloor _roofFloorElement;
public void AssembleBuilding(ushort requiredFloors)
{
//Logic
}
}
But when I want to return this generic list the compiler throws the following error:
Cannot convert expression type 'Pools.MonoPool<Actors.Buildings.ModularBuilding>' to return type 'Pools.MonoPool<UnityEngine.MonoBehaviour>'
Why? How? I'we made MonoPool but i can't return it...
Allright, solution founded: I've changed ILevelGenerator to this:
public interface ILevelGenerator<T> where T : MonoBehaviour
{
public MonoPool<T> Create();
public void Update();
public void SetMode(int mode);
}
And chaged ILevelGenerator inheretor to this:
public class BuildingsGenerator : ILevelGenerator<ModularBuilding>
{
private readonly MonoPool<ModularBuilding> _buildingsPool;
public BuildingsGenerator() {
_buildingsPool = new MonoPool<ModularBuilding>();
}
public MonoPool<ModularBuilding> Create()
{
//Logic...
//Logic...
return _buildingsPool;
}
}
And chenged declaration as well
private readonly ILevelGenerator<ModularBuilding> _buildingsGenerator;
private readonly ILevelGenerator<Cloud> _cloudsGenerator;
So now it works
For a purpose of my university project I need to implement a cyclical linked list, which holds some specific elements. The problem: I want an element of the linked list to have a pointer to a function from the class which creates it. To show the problem in pseudo-C#:
using System;
class Game{
internal void state1(){
Console.WriteLine("Executing state1 code");
}
internal void state2(){
Console.WriteLine("Executing state1 code");
}
Element elem1 = new Elem(state1);
Element elem2 = new Elem(state2);
elem1.Call();
elem2.Call();
}
class Element{
FunctionPointer Call = null;
Element(FunctionPointer function){
Call = function;
}
}
I've tried to use a Delegate, but didn't quite get it right. Is it possible to somehow achieve this using Interfaces?
My delegate try:
using System;
public delegate void MyDelegate();
class Game{
internal void state1(){
Console.WriteLine("Executing state1 code");
}
internal void state2(){
Console.WriteLine("Executing state1 code");
}
Element elem = new Element(new MyDelegate(state1));
}
class Element{
MyDelegate functionPointer = null;
Element(MyDelegate func){
functionPointer = func;
}
}
There are a few ways to do this. Using a delegate would be something like...
public class Game
{
private Element _element = null;
public Game()
{
_element = new Element(state1);
}
internal void state1()
{
Console.WriteLine("Executing state1 code");
}
internal void state2()
{
Console.WriteLine("Executing state2 code");
}
}
public class Element
{
public delegate void FunctionPointer();
private FunctionPointer _function = null;
public Element(FunctionPointer function)
{
_function = new FunctionPointer(function);
_function();
}
}
using interfaces...
public interface IGame
{
void state1();
void state2();
}
public class Game : IGame
{
private Element _element = null;
public Game()
{
_element = new Element(this);
}
public void state1()
{
Console.WriteLine("Executing state1 code");
}
public void state2()
{
Console.WriteLine("Executing state1 code");
}
}
public class Element
{
private IGame _game = null;
public Element(IGame game)
{
_game = game;
_game.state1();
}
}
in my opinion interfaces are better
How can I mark a method to use only if the class object was initialized as static?
For example:
public class A
{
public A()
{
}
public void DoIt()
{
{
public void DoItStatic()
{
}
}
public class B
{
private A _aa = new A();
private static A _aaStatic = new A();
public B()
{
}
public void SomeMethod()
{
_aa.DoItStatic(); //Generate Error for that.
_aaStatic.DoItStatic(); //it's fine
{
}
So, if someone tries to use _aa.DoItStatic(), where _aa is not initialized as static, we generate an error.
Is this possible?
Thanks!
I have searched for creating a Singleton object for a window in WPF.
public static Test DefInstance
{
get
{
if (formDefInstance == null) // formDefInstance.IsDisposed
{
initializingDefInstance = true;
formDefInstance = new cas18();
initializingDefInstance = false;
}
return formDefInstance;
}
set { formDefInstance = value; }
}
But the forDefInstance.IsDisposed is not working and throwing an error.
Any Idea regarding this?
I think everyone should take a look at Jon Skeet's C# In Depth site. If only to read and permanently burn into their brains the singleton patter a-la C#.
http://csharpindepth.com/Articles/General/Singleton.aspx
In your scenario, try to implement this (thread safe, non-lazy):
public sealed class DefInstance
{
private static readonly DefInstance instance = new DefInstance();
static DefInstance()
{
}
private DefInstance()
{
}
public static DefInstance Instance
{
get
{
return instance;
}
}
}
There are also Lazy<T> implementions and various other implementations of the pattern in that site.
I don't know if it's what you want to do but it works for me :
private static MyWindow _defInstance;
public static MyWindow DefInstance
{
get
{
if (null == _defInstance)
{
_defInstance = new MyWindow();
}
return _defInstance;
}
}
In MyWindow code :
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
this.Visibility = Visibility.Hidden;
e.Cancel = true;
}
To use it :
DefInstance.Show();
Then, only one window is display and you use one instance of your window.
you can achieve this by implementing following method
private static volatile DefInstance instance;
private static object syncRoot = new Object();
private DefInstance() {}
public static DefInstance Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new DefInstance();
}
}
return instance;
}
}
before posting the question i did my research for 10 days so really hope someone can shed some light into solving this issue.
The issue is that any bindable control, does not update once the binding list from singleton class is changed. This is a common issue on multi-threaded apps. Most if not all solutions offer suggestions where the bindlinglist or collection is initialized from parent thread, and then some invocation to be made. Not what i'm looking for. The same issue persist if static class is used instead of singleton.
Basically, the application triggers some Tasks, which in turn create object(s) on different business classes. These objects post messages into the bindinglist, which should update the UI listbox, but does not. And yes, the message object is in the list, and binding after the TASK finished works (items displayed). Locking/unlocking object(s) access is also not an issue.
Appreciate any suggestions/solutions
A trimmed down version of business objects:
namespace MyNameSpace
{
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
}
A trimmed down version of another class doing some ops:
namespace MyNameSpace
{
public class WorkDoingClass
{
public WorkDoingClass() { }
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
}
Singleton:
namespace MyNameSpace
{
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public WorkDoingClass() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL};
}
}
}
This is also a trimmed down version from where calls start:
namespace MyNameSpace
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
WorkDoingClass work = new WorkDoingClass();
work.DoSomeOtherWork();
}
Your problem is that the thread(the main UI thread) making the listbox is different from the thread(the worker thread) modifying the collection.
Try the following code. It could solve your issue. I use SynchronizationContext to synchronize the two threads, which serves as the same function with Control.Invoke().
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
WorkDoingClass _work;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
_work = new WorkDoingClass(SynchronizationContext.Current);
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
_work.DoSomeOtherWork();
}
}
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
public class WorkDoingClass
{
private SynchronizationContext _syncContext;
public WorkDoingClass() { }
public WorkDoingClass(SynchronizationContext _syncContext)
{
// TODO: Complete member initialization
this._syncContext = _syncContext;
}
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
_syncContext.Send(DoWork, null);
}
private static void DoWork(object arg)
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public AllMessages() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL; }
}
}
}