I am trying to create a base class with some functionality shared between all derived classes. And all derived classes should be Singletons. Below a pseudo example.
class ExtensionSettings
{
public string GetConfigHtml()
{
// creat conifig html for all properties
}
public void SaveSettings()
{
// save stuff
}
}
class SettingsA : ExtensionSettings
{
private static SettingsA instance;
public static SettingsA Instance {get {return instance ?? (instance = new SettingsA());}}
public string setting1{get;set;}
public string setting2{get;set;}
}
class SettingsB : ExtensionSettings
{
private static SettingsB instance;
public static SettingsB Instance {get {return instance ?? (instance = new SettingsB());}}
public string setting1{get;set;}
public string setting2{get;set;}
}
static void Main(string[] args)
{
System.Console.WriteLine(SettingsA.Instance.setting1);
System.Console.WriteLine(SettingsB.Instance.setting2);
}
Is it possible to move the instancing part to the ExtensionSettings base class?
base class doesn't know about the rest of the object to be instantiated.
basically, when you derive from a base class, the extra logic added in derived class
is hidden from base class. therefore, doing instantiation in the base class is not
possible.
Related
Recently, I had a need to process the private data contained in the base class using the methods of the child class. My base class could only contain domain-specific types (it only represents data). So first I decided to create a child-class in another project and implement the processing logic in it. But the problem is that once you create an instance of the base class, you can't cast it to the child type:
public class A
{
protected int member1;
public A(int value)
{
member1 = value;
}
}
public class B : A
{
public B (int value) : base(value)
{ }
public void DoSomething()
{
Console.Write(member1 * member1);
}
}
class Program
{
static void Main(string[] args)
{
A obj1 = new A(5);
B obj2 = (B)obj1; // InvalidCastException
obj2.DoSomething();
}
}
And I started thinking towards extension methods. However, you can't just access the protected fields of the class from them. In the end, I tried to combine the two approaches.
Here's my solution:
Make sure that you are allowed to add new methods to your base class and that your class is not sealed.
Add protected static method which returns the protected member you need.
Create an Extension class for your base class.
In extension class create a private nested class.
Inherit your nested class from your base class.
Create static method in nested class and implement the processing logic in (you can call static protected method from base class to get protected member from base class).
Create extension method in extension class and call static method of nested class in it.
The sample code is shown below:
public class A
{
protected int member1 = 0;
public A() {}
public A(int value)
{
member1 = value;
}
protected static int GetProtectedMember(A objA)
{
return objA.member1;
}
}
public static class AExtensions
{
public static void DoSomething(this A objA)
{
B.DoSomething(objA);
}
private class B : A
{
public static void DoSomething(A objA)
{
// objA.member1 // it's not allowed
int protectedFromA = A.GetProtectedMember(objA);
int sqr = protectedFromA * protectedFromA;
Console.WriteLine(sqr);
}
}
}
class Program
{
static void Main(string[] args)
{
A obj1 = new A(5);
obj1.DoSomething(); // 25
}
}
This way you can keep the classes that represent the data in a separate project and have multiple implementations of processing this data in different projects.
Say I have a generic class Foo, that has a variable that is protected
public class Foo<T>
{
protected bool knowsFu;
}
I also have 2 sub-classes: Bar and Pipe
public class Bar : Foo<Bar> {}
public class Pipe : Foo<Pipe> {}
It is actually possible for me to access the knowsFu in Pipe FROM Bar, e.g.:
public class Bar : Foo<Bar>
{
void UpdateFuInOtherClass(Pipe p)
{
p.knowsFu = false;
}
}
Is this intended behaviour? (If so, what would be the usecase?)
Is there a way for me to prevent other Foo-Subclasses from modifying/reaching the protected variable inside of my current subclass?
More specifically: I'm using a generic class to implement the Singleton-Pattern:
https://en.wikipedia.org/wiki/Singleton_pattern
However, I'm currently able to access any singleton's protected instance-variable, as long as I am inside of another Singleton. Is there a way to prevent this?
EDIT: It might be relevant to note that the protected variable (knowsFu) is actually STATIC as well.
EDIT2: Ok, maybe the example was abit too generic.. here's how I'm actually currently implementing it:
why use Singleton? A:The platform I'm working on is Unity3D, in which the pattern is used frequently
I have a generically typed abstract class SingletonBehaviour
public abstract class SingletonBehaviour<T> where T : MonoBehaviour
{
public static T Instance { get { return instance; } }
protected static T instance { get; private set; } }
// Loading is done through Unitys Awake-Method
}
One of the Singleton-Objects that I'm using is the APIManager
public class APIManager : SingletonBehaviour<APIManager>
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
However, since most of my projects need some better API-implementation than that, what I'm currently doing is:
public class ProjectAAPIManager : APIManager
{
// Overriding Instance so my return value is not APIManager but instead ProjectAAPIManager
public static new ProjectAAPIMamager Instance { get { return (ProjectAAPIManager)instance; } }
}
This ^ is the reason my (inner) instance-variable is protected, and not private.
However, because of this, any other SingletonBehaviour in my project can now access the (inner) instance-variable on my ProjectAAPIManager
public class GameController : SingletonBehaviour<GameController>
{
private void AMethod()
{
// Accessing inner variable instead of public one
ProjectAAPIManager.instance.DoSomething();
}
}
As it's only the getter, this currently does not really matter. But what if I'd need access to the setter in my subclass as well?
Also: would it be worth it to generically type my APIManager as well?
Your question is nothing short of bewildering. How can you make a protected member not be accesible from a derived class? Well, a good start is not making it protected.
protected is by definition exactly what you don't want, so don't use it! Use private instead.
If what you are asking is how to make it a readonly member when accessed from derived types, you have two options:
Declare it as readonly in the base class if possible.
Use a protected property instead with a private setter.
Many novice coders seems to think protected members aren't part of the public surface of the type but they really are, as long as the class can be extended. As such, the rules of public members apply: never expose public fields unless they are readonly or constants, use properties instead.
You should not have classes that implement your generic singleton class.
Otherwise, by default, your protected fields will be accessible by the subclasses (it's what "protected" keyword does)
Instead, you should do something like this:
class Program
{
static void Main(string[] args)
{
var barInstance = Foo<Bar>.GetInstance();
}
}
public class Foo<T> where T : new()
{
protected bool knowsFu;
private static T _instance;
public static T GetInstance()
{
if (_instance == null)
_instance = new T();
return _instance;
}
}
public class Bar
{
public Bar()
{
}
}
Edit 1:
To use a singleton, you should not make another class implement the singleton behavior (This is not how the singleton pattern works).
To use the same classes as your second example, you should do something like this.
public class SingletonBehaviour<T> where T : new()
{
public static T Instance
{
get
{
if(instance == null)
instance = new T()
return instance;
}
}
private static T instance { get; set; }
}
public class APIManager // This class should not inherit from the SingletonBehavior class
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
public class ProjectAAPIManager : APIManager
{
public ProjectAAPIManager GetInstance() => SingletonBehavior<ProjectAAPIManager>.Instance();
}
I Am getting a warning message in my class, like
Add a Protected constructor or the static keyword to the class declaration
Solution
The error is gone after I tried both the below ways,
static class without constructor
public static class Program {
}
Non static class with protected using constructor
public class Program
{
protected Program() { }
}
Question:
So What is the difference between Static Class vs Protected Constructor which is mentioned in my above solution? And which one is best to use?
A static class doesn't need an instance to access its members. A static class cannot have instance members (e.g. public int MyNumber; is not allowed on a static class because only static members are allowed on a static class). Both instance and static members are allowed on a non-static class though. A class with a protected constructor can only have an instance created by itself or something that inherits from it.
public class Program
{
protected Program()
{
// Do something.
}
public static Program Create()
{
// 100% Allowed.
return new Program();
}
public void DoSomething()
{
}
}
public static class AnotherClass
{
public static Program CreateProgram()
{
// Not allowed since Program's constructor is protected.
return new Program();
}
}
public class SubProgram : Program
{
protected SubProgram()
{
// Calls Program() then SubProgram().
}
public new static Program Create()
{
// return new Program(); // We would need to move the SubProgram class INSIDE the Program class in order for this line to work.
return new SubProgram();
}
}
Program.Create(); // Can be called since Create is public and static function.
Program.DoSomething() // Can't be called because an instance has not been instantiated.
var test = Program.Create();
test.DoSomething(); // Can be called since there is now an instance of Program (i.e. 'test').
AnotherClass.CreateProgram(); // Can't be called since Program's constructor is protected.
SubProgram.Create(); // Can be called since SubProgram inherits from Program.
As for performance, this distinction doesn't really have much to do with performance.
You probably only have static members in the class and the code analyser assumes that your intention is to not be able to create instances of the class so it is asking you to either make the class static
public static class Program {
//...static members
}
or put a protected/private constructor
public class Program {
protected Program { //OR private
}
//...static members
}
to prevent instances of that class from being initialized.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated.
Reference Static Classes and Static Class Members (C# Programming Guide)
The protected constructor means that only derived classes can call the constructor
and a private constructor wont allow any other classes to initialize the class with a private constructor
A static constructor is called when the class type is instantiated. The protected constructor is called when an instance of a class is created. The protected part means only classes that inherit the class can call it.
Static Constructor: Called once when the class type is instantiated and is used to initialize static members. Does not create an instance of the class.
Protected Constructor: A constructor that can be called only by the class or a class that inherits it.
The best practices for this is that you should have a static constructor for initializing static members and a protected constructor if you only want classes that inherit to be able to create an instance of your class. You can have both.
public class MyClass
{
static readonly long _someStaticMember;
private bool _param;
static MyClass()
{
//Do Some Logic
_someStaticMember = SomeValueCalculated;
}
protected MyClass(bool param)
{
_param = param;
}
}
public class ChildClass: MyClass
{
public ChildClass(bool param) : base(param);
}
public class NotChildClass
{
public MyClass someObject = new MyClass(true); //Will Fail
}
I'm trying to instantiate an inherited class from a Base class.
I have tried with this code:
public class BasicClass
{
private static BasicClass instance;
private BasicClass() { }
public static BasicClass Instance
{
get
{
if (instance == null)
{
var dataType = MethodBase.GetCurrentMethod().DeclaringType;
instance = (BasicClass)Activator.CreateInstance(dataType);
}
return instance;
}
}
}
public class MyClass1 : BasicClass
{
}
public class MyClass2 : BasicClass
{
}
And then call it :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var o = MyClass2.Instance;
Text = o.GetType().Name;
}
}
I my small demo I've used a WinForm application but that's just for testing.
My problem is that I get an instance of BasicClass not MyClass2 Can I some how get MyClass2
Can I some how get MyClass2?
No, at least not with the approach that you took. GetCurrentMethod() will not get you the method in the caller, it will give you the method that implements the getter property.
Moreover, consider this declaration:
private static BasicClass instance;
There's only one instance in your program, no matter how many subclasses you create. The problem is that if MyClass2 creates an instance and stores it in BasicClass.instance, there's no place for MyClass1's instance to go.
One approach that you could take would be using a dictionary that maps subtypes to instances, and a generic method for accessing them, like this:
private static IDictionary<Type,BasicClass> instances = new Dictionary<Type,BasicClass>();
...
public static T GetInstance<T>() where T : BasicClass {
BasicClass res;
if (!instances.TryGetValue(typeof(T), out res)) {
res = (BasicClass)Activator.CreateInstance(typeof(T));
instances.Add(typeof(T), res);
}
return (T)res;
}
...
var o = MyClass2.GetInstance<MyClass2>();
You can create a templated base class:
public abstract class Singleton<T> where T : class
{
private static readonly Lazy<T> instance = new Lazy<T>(() => CreateInstance());
public static T Instance { get { return instance.Value; } }
private static T CreateInstance()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
And then inherit it:
public class MyClass1 : Singleton<MyClass1>
{
}
Short answer is: Singleton pattern cannot be inherited. This is because static fields (Instance, for ex.) are declared in special so-called Type Object? which in your case is BaseType and so they no nothing about their children
What do you want to achieve?
You can implement a wrapper like this:
public class Singleton<T>
where T:class, new()
{
private static readonly Lazy<T> _instance = new Lazy<T>(()=>new T());
public static T Instance
{
get { return _instance.Value; }
}
}
See answer below, which provides cool implementation of Singleton wrapper
This question already has an answer here:
Global instances of class
(1 answer)
Closed 9 years ago.
So I have a class.
I then make an instance somewhere:
Class1 somesinstance = new Class1;
Now I want to access this instance anywhere, is that possible?
Ah, the elusive singleton pattern.
If you have a little spare time, I would highly recommend Jon Skeet's article on the subject: http://csharpindepth.com/Articles/General/Singleton.aspx
Here is a simple example:
public sealed class YourSingleton
{
private static readonly YourSingleton instance = new YourSingleton();
static YourSingleton() {}
private YourSingleton() { }
public static YourSingleton Instance
{
get { return instance ; }
}
}
If you only need a single instance, use the singleton pattern:
public class Class1
{
private Class1()
{
...
}
private static readonly Class1 _instance = new Class1();
public static Class1 Instance { get { return _instance; } }
}
And access the instance like this:
Class1.Instance
Otherwise, just expose it as a static property in a class.
You can the Singleton Pattern as follows:
public class MyClass
{
private static MyClass myClass;
public static MyClass MyClassInstance
{
get { return myClass ?? (myClass = new MyClass()); }
}
private MyClass()
{
//private constructor makes it where this class can only be created by itself
}
}
The instance can then be accessed globally like
MyClass.MyClassInstance
If your anywhere mean your solution - You can use a static class with a static property
public static class Shared
{
private static Class1 _myclass;
public static Class1 MyClass{
get
{
return _myclass??(_myclass=new Class1());
}
}
}
You could create a static class that contains shared instances accessible from every class in you application.
public static class SharedResources
{
public static Class1 obj1 {get; set;}
public static Class2 obj2 {get; set;}
// ...
}