I have an abstract base class, and subclasses who all have an automatically generated Instance static field of their own type, done through using genericity "in between" the base and sub classes (see code below).
When those instances are created, I register them in a dictionary based on specific "identifying" fields overwritten in subclass constructors, in order to access them somewhere else in the code.
I could register them in their constructors, however I don't want to have to drag and copy/paste this same bit of code in every such subclass in order to register them.
public abstract class BaseClass
{
// Declaration of fields and methods
}
public class GenericBaseClass<T> : BaseClass where T : GenericBaseClass<T>
{
private static T instance = ((T) Activator.CreateInstance(typeof(T), true)).Register();
public static T Instance => instance;
public T Register()
{
// Registers Instance in a dictionary.
}
}
public class Subclass1 : GenericBaseClass<Subclass1>
{
private Subclass1()
{
// Modification of protected fields.
}
}
Doing this enables me to call Subclass1.Instance, and by doing so, this instance gets registered in my dictionary, however it doesn't get registered before I try to access it, and only Subclass1 gets that treatment, not other subclasses.
I followed this answer https://stackoverflow.com/a/34726769/13738641 (in the updated section) and made a static constructor for BaseClass and for GenericBaseClass hoping it would initialize static fields for those subclasses, to no avail.
It appears from debugging that the BaseClass static constructor is indeed called, and it does fetch the right subclasses, but it doesn't throw an error, nor does it calls the subclass (static) constructors. Now I could be going crazy, but I could have sworn it worked once before I tried modifying something before reverting back to that, only for it not to work anymore.
I've tried adding a static constructor to the generic class which I hoped would be called once for each subclass, but this constructor only gets called once (when I access some subclass's instance in order to trigger the BaseClass static constructor call).
Any suggestion on what to do to achieve this? I accept suggestion on other ways to achieve something similar (i.e. keep a dictionary generated at runtime with instances of my classes), the subclasses being singletons isn't critical, so maybe I could register constructors instead of instances in the dictionary? I have no idea if that is even possible, with each constructor returning a different type.
You could loop through the types in your assembly and check if they implement the generic class, and then invoke the static constructor of the generic class (which will implicitly invoke the static constructor of the sub class because of Activator.CreateInstance) by calling RuntimeHelpers.RunClassConstructor. So just add a method that does that can call it:
public static void RegisterAll()
{
foreach(var type in typeof(BaseClass).Assembly.GetTypes().Where(t => t.BaseType.IsGenericType &&
t.GetGenericTypeDefinition() == typeof(GenericBaseClass<>)))
{
RuntimeHelpers.RunClassConstructor(type.BaseType.TypeHandle);
}
}
Related
I came across a source code with a nested class like this:
public class OuterClass
{
// code of the outer class
protected class NestedClass
{
private string myVar;
private NestedClass() {} // <--- empty private ctor
public NestedClass(string myVar)
{
this.myVar = myVar;
}
}
}
What could be the reason to create this empty private constructor?
I know when implementing a singleton the constructor must be private to prevent other classes to create an instance. However in the case the is another public constructor, so this cannot be the reason.
One reason I thought of would be to not allow the creation of an instance without a value for the variable, that is passed as parameter to the public constructor, but as far as I know this shouldn't be possible when the is simple no other constructor than the public constructor with parameter. Is that correct?
Edit: A answer that was deleted now, mentioned the default constructor. As far as I know a "hidden" default constructor only exists if there is no manually written constructor at all. This is described here:
These constructors are injected into all class declarations that do not introduce other constructors.
Therefore the empty constructor of my nested class, is not a default constructor, but simply a constructor without parameters. I assume that this is the case for top-level classes and nested classes alike.
If you have a non-default constructor and do not specify a default constructor, it will not be possible for any code to access the default constructor, because the compiler will not create one.
If you have a non-default constructor and also specify a private default constructor then it is possible for a NestedClass method to use the default constructor. Your code does not do this, so it is not necessary to provide a default constructor (private or otherwise).
There also an obscure case where it can make a difference: By providing the default NestedClass constructor, you enable reflection to access it.
The following program demonstrates.
If you run it, it will print "Demo.OuterClass+NestedClass".
If you comment-out the private default NestedClass constructor and run it, it will crash.
Other than this unlikely case, I can see no sensible reason to provide the private constructor.
using System;
using System.Reflection;
namespace Demo
{
public class OuterClass
{
protected class NestedClass
{
private string myVar;
private NestedClass(){} // Commenting-out this line will cause the reflection to break.
public NestedClass(string myVar)
{
this.myVar = myVar;
}
}
}
public class MyDerivedClass: OuterClass
{
public MyDerivedClass()
{
Type type = typeof(NestedClass);
var ctor = type.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic, null, Type.EmptyTypes, null);
var nested = (NestedClass) ctor.Invoke(null);
Console.WriteLine(nested);
}
}
public static class Program
{
private static void Main()
{
var test = new MyDerivedClass();
}
}
}
If you don't want to explicitly allow reflection to call the private default constructor, then I would say that there is indeed no point in providing it, and you should remove it from the code.
I think this means that only this class can create instances of itself using this constructor. Does the code in the class call this constructor anywhere?
Normally you'd have a private constructor if the class wanted to restrict you to calling some sort of factory method defined on it in order to create it, but as there's another constructor defined then this doesn't seem to be the case.
You can use reflection to locate the private constructor, and once you've got the ConstructorInfo for the private constructor you can invoke it in order to create an instance of the class, but this would be a very niche thing to do!
I have a class defined as:
public class DatabaseEntity<T> where T : DatabaseEntity<T> {
public static string Query { get; protected set; }
public static IList<T> Load() {
return Database.Get(Query);
}
}
public class Node : DatabaseEntity<Node> {
static Node() {
Node.Query = #"SELECT Id FROM Node";
}
}
When I run Node.Load() from a codebehind (Window.xaml.cs) the Node's static constructor never fires; or at least doesn't hit a breakpoint and does not set Node.Query to anything other than null.
Is there any reason why this might occur?
Solution
Check out the answers below for a few solutions. For my case, I decided to simply make the Query variable public, and set all instances of Query in one place. (Not ideal, but it works.)
The problem lies in your assumptions about when a static constructor is called. The documentation, which isn't the clearest, states that
It is called automatically before the first instance is created or any static members are referenced.
You may assume that if you call
Node.Load();
that you are calling a static method on the Node class, but in fact you're calling it on the base class, as that is where it is implemented.
So, to fix this, you have two choices. First, you can trigger the static constructor explicitly by creating a new instance of the Node class prior to calling Load()
var foo = new Node(); // static ctor triggered
Node.Load();
or create a protected virtual member that the base class can call in order to get the query value (can't use abstract here, unfortunately)
public class DatabaseEntity<T> where T : Derp {
protected abstract string Query { get; }
public static IList<T> Load() {
return Database.Get(new DatabaseEntity<T>().Query);
}
}
Both of which are hacky. Better to dispense with the statics altogether and go with instance methods. Statics should be used sparingly, as they result in tight coupling and other design headaches such as this.
Yes, static constructors will not be called till the members of the class is first accessed or first instance is created.
In your case you're accessing DatabaseEntity<T>.Load, so static constructor of DatabaseEntity<T> will be called not its derived class ones.
Even though you call Node.Load it is mapped to DatabaseEntity<Node> at compile time. So technically you're not accessing Node class at all.
You can also call class constructors directly using System.Runtime.CompilerServices and the RuntimeHelpers type by doing something as follows:
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
So for example you could use reflection to loop over all types in an inheritance chain and call each of the static constructors.
The question title seems a little bit odd doesn't it. Anyway. So I have one base class which has some private fields, protected properties and a single constructor that takes one argument and I have several sub classes of that base class. whenever any of those subclass methods are called the sub classes are required to be instantiated and after the method is done executed the object is destroyed so if the method will be called again new instance of the class should be made. (Its a WCF service) Now, the thing I want to do is the following. whenever the certain sub class constructor is called I call the base class constructor explicitly with some certain parameter (different for every sub class, Note: no sub class methods are the same), When the base class constructor is called I want to check something according to that argument and if it passes the check then I want to allow the execution of sub class method. In any other case I want it NOT to run the sub class method. So I want something like this. when the method is called the sub class has to be constructed and for that, base class has to be constructed as well and if the check fails in the base class' constructor I want to prevent that method from running. I can just have a bool property and set it in base class' constructor and check it on every method call. but I want to make something more general. May be the way that I'm suggesting Is not right either. So you understand what I want I guess. Any suggestion would be appriciated. thanks in advance
class BaseClass
{
private bool _isValid;
private SomeService someService;
public BaseClass(SomeEnum value)
{
someService = new SomeService();
if (someService.Validate(value))
{
_isValid = true;
}
}
protected internal bool IsValid { get { return _isValid; } }
}
class SubClass : BaseClass
{
// object declaration
public SubClass () : base(SomeEnum.SomeValue)
{
// constructing some objects here
}
public Response Operation('parametereGoHere')
{
if (IsValid)
{
// perform operation. construct Response object and return it
}
}
// other methods omitted.
}
So whenever the Operation() method is called SubClass has to be constructed which causes the BaseClass to be constructed and the base class sets the value of _isValid which is then use to check for validity, but I wanted to make something more general. lets that instead of just setting the value of _isValid to true just do nothing or set some other properties and if the Valiate() failed just stop the execution and don't to anything at all. In this case the calling routing wouldn't be able to call Operation() if we somehow managed to stop the construction of class. If it's not possible I'm perfectly happy with the solution I have right now. But if it is I will be glad to see that. Note: In every sub class, methods are different and I have to check IsValid to allow the execution of method.
You should be able to use the out parameter to get the constructor to return a value.
Very hard to follow what you want, but it sounds like you want a case where the base constructor doesn't do anything sometimes. Then simply make a base constructor that doesn't do anything, and call it (with the : base() call). Use a dummy argument if necessary.
class A {
public A() { a= 1; }
public A(double dummy); { }
}
class B
public B() : base() { // calls the base constructor that does something
}
public B(int) : base(1.0) {// class the base construct that does nothing
}
}
Ok, I have a singleton class GraphMaster which contains a number of system-wide values. I have a subclass GraphObject : GraphMaster which has graph specific data. By subclassing, I can access members of either the global class or subclass. And by using a singleton class, I can change the global variables anywhere and have them be reflected in all the subclasses.
However, I'm getting stuck because the base class's constructor wants to call the singleton class's constructor, but it can't as it's marked private.
how do I get around this? Is what I'm trying to do possible? I went down this path due to responses to this post: Can I make a "global" object to store variables for multiple objects?
For example,
public class GraphMasterObject {
private static GraphMasterObject instance;
private GraphMasterObject() { }
}
public static GraphMasterObject Instance {
get {
if (instance == null) instance = new GraphMasterObject();
return instance;
}
}
public int globalVar=10;
}
public class GraphObject : GraphMasterObject {
public GraphObject() {
}
public int localVar=20;
}
I want to be able to do
GraphObject go = new GraphObject();
go.globalVar <- this is 10
GraphMasterObject.Instance.globalVar = 20;
go.globalVar <- now this is 20
Ok, I have a singleton class GraphMaster which contains a number of system-wide values. I have a subclass GraphObject : GraphMaster which has graph specific data.
That's a problem to start with. As soon as you have a class which has subclasses, that it by definition not a singleton. Someone can add another subclass at any point, and even if you only have one instance of each subclass, you'll have two distinct instances which are compatible with the base class.
You could add something in the base class constructor to throw an exception if there's already an instance, but it would be pretty smelly. Fundamentally, singletons are incompatible with subclassing. Rethink your design. (Ideally, avoid the singleton pattern in the first place, but that's another matter...)
Although a static class has only one instance and can't be instantiated, a class with a private constructor can't be instantiated (as the constructor can't be seen), so every time you call this class, this is the same one instance?
Factory classes always follow the last convention (instance class with private constructor). Why is this?
Thanks
There's nothing stopping the class with the private constructor from having a public static method which returns instances of the class:
public class NoPublicConstructor
{
private NoPublicConstructor()
{
}
public static NoPublicConstructor NewInstance()
{
return new NoPublicConstructor();
}
}
As you can see, the static method does not return the same one instance.
edit: One of the reasons factory classes do this is to be able to separate responsibility in future versions: while your code always calls the factory creation method, the author may move all the "guts" out of that class into a different one and your code won't need to know the difference. Calling that class' (public) constructor ties it to an extent to the original class implementation.
You can't* get an instance from outside the class, but you can from inside. A static method or an inner class can create and return an instance of the class with a private constructor. The static class cannot be instanced by anything.
class Foo
{
private Foo()
{
}
public class Bar
{
public Bar()
{
}
public Foo GetFoo()
{
return new Foo();
}
}
}
..
Foo.Bar fooBar = new Foo.Bar();
Foo foo = fooBar.GetFoo();
Edit: *I use the term "can't" loosely. Brian Rasmussen pointed out in the comments to the OP that another method to obtain an instance is through a call through System.Runtime.Serialization.FormatterServices, and this is external to the class itself.
Foo foo = (Foo)System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof(Foo));
Creating a class with private constructor is the common pattern for implementing a "Singleton" object.
The Singleton usually will instantiate an instance of itself, and only allow access to it through a static "Instance" property, which means there's only ever one instance of the class.
The advantage of using a Singleton over a purely static class is that you can utilize interfaces and different implementation classes within the singleton. Your "Singleton" might expose an interface for a set of methods, and you can choose which exact implementation class to instantiate under the covers. If you were using a purely static class, it would be hard to swap out a completely different implementation, without impacting other code.
The main downside of Singleton is that it's difficult to swap out the implementation class for testing, because it's controlled within the Singleton private methods, but there are ways to get around that.