If I want a constructor that is only accessible from child classes I can use the protected key word in the constructor.
Now I want the opposite.
My child class should have an constructor that can be accessed by its base class but not from any other class.
Is this even possible?
This is my current code. the problem is that the child classes have a public constructor.
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(dataSet);
}
}
public class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(DataSet dataSet)
{
}
}
I think you have two options:
Make the child constructor internal. This means it will be accessible from all types in the same assembly, but that should be enough in most cases.
Make the child classes nested in the base class:
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
private class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
}
This way, BaseClass can use the constructor, but no other outside type can do that (or even see the child class).
I think I just solved it by myself. After reading svicks solution with nested classes, I thought why not use an protected nested class as an argument?
Nobody from outside is able to create an instance of Arg and the public contructors from my child classes can only be used by BaseClass which can create Arg<T> instances.
public abstract class BaseClass
{
protected class Arg<T>
{
public T Value { get; set; }
public Arg(T value) { this.Value = value; }
}
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(new Arg<DataTable>(dataTable));
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(new Arg<DataSet>(dataSet));
}
}
public class Child1 : BaseClass
{
public Child1(Arg<DataTable> arg) : this(arg.Value) { }
private Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(Arg<DataSet> arg) : this(arg.Value) { }
public Child2(DataSet dataSet)
{
}
}
Answer to the question is "NO"
There is no such thing exists in the OOP that allow child class constructor to visible only to the Base Class of it...
One could enforce the desired behavior at run-time by having the base constructor accept a ref parameter, and do something like (not threadsafe):
private int myMagicCounter;
public DerivedClass makeDerived(whatever) // A factory method
{
DerivedClass newThing;
try
{
... do whatever preparation
newThing = new DerivedClass(ref myMagicCounter, whatever);
}
finally
{
... do whatever cleanup
}
return newThing;
}
BaseClass(ref int magicCounter, whatever...)
{
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
myMagicCounter++;
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
}
Note that it will be impossible for a derived class constructor call to get control without having done the factory method's preparation, or to return control to its caller without doing the factory method's cleanup. There will, however, be nothing to prevent the derived-class constructor from passing its partially-constructed instance to outside code which may do whatever it likes with it for an arbitrary amount of time before returning control to the factory method.
Pass and register a factory delegate from the type initializer of derived classes then you just get the job done:
public abstract class BaseClass {
static readonly Dictionary<Type, Delegate>
m_factories = new Dictionary<Type, Delegate> { };
public static BaseClass CreateInstance(DataTable dataTable) {
var type = typeof(Child1);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child1)m_factories[type].DynamicInvoke(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet) {
var type = typeof(Child2);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child2)m_factories[type].DynamicInvoke(dataSet);
}
protected static void AddFactory<TArgs, T>(Func<TArgs, T> factory) {
m_factories.Add(typeof(T), factory);
}
}
public class Child1:BaseClass {
Child1(DataTable dataTable) {
}
static Child1() {
BaseClass.AddFactory((DataTable dt) => new Child1(dt));
}
}
public class Child2:BaseClass {
Child2(DataSet dataSet) {
}
static Child2() {
BaseClass.AddFactory((DataSet ds) => new Child2(ds));
}
}
public static class TestClass {
public static void TestMethod() {
var child2 = BaseClass.CreateInstance(new DataSet { });
var child1 = BaseClass.CreateInstance(new DataTable { });
}
}
If all of the derived classes inherited from the base class directly then don't you worry about the collision of registration -- no body can access a constructor from another class.
For TArgs of Func<TArgs, T> you might want to declare it like variadic generic arguments although it's just not a feature of C♯, Tuple is one of the approaches to simulate it. For more information on this topic, you might want to have a look at:
Simulate variadic templates in c#
Related
I have a base class that takes two arguments in its constructor:
public class BaseClass {
public BaseClass(string key, object value) { ... }
}
My derived class is constructed differently, using a single complex argument that I can then split into the base class arguments.
public class DerivedClass : BaseClass {
public DerivedClass (string keyValuePair)
: BaseClass( SomethingExpensive(keyValuePair).Key,
SomethingExpensive(keyValuePair).Value) { }
private static KeyValuePair<string,object> SomethingExpensive(string input) {
// Do expensive things
return new KeyValuePair<string,object>(derivedKey, derivedValue);
}
}
Given that I have no control over BaseClass and cannot give it a new constructor, I'm trying to find any way that I can pass along those arguments without calling SomethingExpensive twice.
I thought about using an out parameter to generate a new identifier for the additional constructor arguments during the first invocation:
public class DerivedClass : BaseClass {
public DerivedClass (string keyValuePair)
: BaseClass( SomethingExpensive(keyValuePair, out object _value), _value) { }
private static string SomethingExpensive(string input, out object value) {
// Do expensive things
value = derivedValue;
return derivedKey;
}
}
But this is rejected in the current framework with the error:
Error CS8107 Feature 'declaration of expression variables in member initializers and queries' is not available in C# 7.0. Please use language version 7.3 or greater.
Any alternative ideas?
I can think of 2 separate approaches, albeit not outright solutions:
You can cache the result of parsing the key value pair, so that the 2nd call is not expensive
You can use a has-a rather than a is-a relationship model. So that the base class is not derived, but a contained object, wrapped and exposed by the same interface.
Hope this helps.
Just add an adapter class between BaseClass and DerivedClass
public class BaseClass {
public BaseClass(string key, object value) { ... }
}
public class AdapterClass : BaseClass {
public AdapterClass (SomethingExpensive se) : BaseClass(se.key, se.value) { ... }
}
public class DerivedClass : AdapterClass{
public DerivedClass (string keyValuePair) : AdapterClass(SomethingExpensive(keyValuePair)) { }
private static KeyValuePair<string,object> SomethingExpensive(string input) {
// Do expensive things
return new KeyValuePair<string,object>(derivedKey, derivedValue);
}
}
Inspired by #alex's solution, but without the need for an additional class:
public class DerivedClass : BaseClass {
public DerivedClass (string keyValuePair)
: this(SomethingExpensive(keyValuePair)) { }
private DerivedClass (Tuple<string,object> arguments)
: BaseClass(arguments.Item1, arguments.Item2)
private static Tuple<string,object> SomethingExpensive(string input) {
// Do expensive things
return Tuple.Create(derivedKey, derivedValue);
}
}
I have a class A, and a class AStore. My requirement is to prevent all other methods from initializing an instance of class A, which they should get an instance from AStore. In addition, I also need to access the member functions of A from the instance.
Factory pattern is not suitable for this problem as the constructor of A is still public. Ideally, it should throw compilation error when calling the constructor of class A while having access to its member functions.
Can I get C# solutions to this?
For restricting others to create an instance of class A you can use a private constructor and a static factory method to get the instance of that class.
public class A
{
private A(){}
public static A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
To enforce instance creation of A only via Astore you can use protected modifier and derive AStore from A. That way, only AStore will have access to its protected members like 'constructor' or 'factory method':
public class Astore : A
{
public A GetInstanceOfA()
{
return base.GetInstance();
}
}
public class A
{
protected A() { }
protected A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
//Usage
public class ConsumerClass
{
public void Test()
{
var a = new A(); // Compile error
a = new Astore().GetInstanceOfA();
a.MemberFunctionOfA();
}
}
But there're still chances that another class say 'UnWantedStore' can derive from A and serve instance of A.
Another approach is moving AStore and A classes to the dedicated project and make constructor of A class internal.
// Project A
namespace ProjectA
{
public class A
{
public int PropertyOne { get; set; }
public string PropertyTwo { get; set; }
internal A() {}
}
public class AStore
{
public A CreateA()
{
//internal constructor can be used
return A();
}
}
}
// Project ConsumerOfA
namespace ConsumerOfA
{
public static void UseA()
{
var store = new AStore();
var instanceOfA = store.CreateA();
// have access to the A's public members
}
}
With this approach you will get perfect encapsulation you trying to achive.
Abstract classes to the rescue!
Indeed, there's yet another possible approach! I've never used it but it might work in your scenario. See the following code sample:
public abstract class A
{
public string Text { get; set; }
public string SayHello() => "hello world!";
}
public class AStore
{
private class AInternal : A {}
public void DoStuff()
{
A a = new AInternal();
a.Text = "whatever";
string helloText = a.SayHello();
}
}
Let's explain the approach:
Class A is abstract, therefore it can't be instantiated.
Class AStore implements a private nested class called AInternal which just inherits A to let AStore members be able to instantiate A. Since AInternal is private, no other class than AStore can instantiate AInternal!
Class AStore can access public A members because AInternal inherits A!
You can do this with reflection too:
public class ClassA
{
// The constructor(s) have to be private
private ClassA() { }
// Whatever other code you want
}
public class ClassB
{
public static ClassA GetClassAInstance()
{
// Use reflection to get the private default constructor
ConstructorInfo constructor = typeof(ClassA).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
ClassA instance = constructor.Invoke(new object[] { }) as ClassA;
return instance;
}
}
You can find more information on the GetConstructor method here.
During some research, I ran into an inheritance pattern using generics I have not seen before.
http://thwadi.blogspot.ca/2013/07/using-protobuff-net-with-inheritance.html
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>
{
//...
}
public class DerivedClass : BaseClass<DerivedClass>
{
//...
}
Usage:
static void Main(string[] args)
{
DerivedClass derivedReference = new DerivedClass();
//this looks odd...
BaseClass<DerivedClass> baseReference = derivedReference;
//this doesn't work
//BaseClass baseClass = derivedReference;
}
I was surprised that this even worked, I had to test it myself. I still can't understand why you would want to do this.
The only thing I could come up with, is preventing different derived classes from being stored in a collection together as their base class. This may be the reason, I guess I'm just curious to the application.
It is called the Curiously recurring template pattern it is often used to allow methods in the class to use the type of the derived class as a passed in or returned parameter.
For example, this is Clone method implemented so that only each layer needs to add it's own properties to the method as it goes down the chain.
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>, new()
{
public int Foo {get;set;}
public virtual TClass Clone()
{
var clone = new TClass();
clone.Foo = this.Foo;
return clone;
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
public int Bar {get;set;}
public override DerivedClass Clone()
{
var clone = base.Clone();
clone.Bar = this.Bar;
return clone;
}
}
Usage:
static void Main(string[] args)
{
DerivedClass derivedReference = new DerivedClass();
DerivedClass clone = derivedReference.Clone();
}
As an example of usage, suppose you want to implement some chainable builder methods on the base type and derived type like this:
var d = new DerivedClass();
d.SetPropertyA("some value").SetPropertyB(1);
While SetPropertyA belongs to base class and SetPropertyB belongs to derived class.
By implementing classes like below, when chaining methods, after calling SetPropertyA because the return value is of type DerivedClass you can call SetPropertyB:
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>
{
public string A {get ; set; }
public TClass SetPropertyA(string value)
{
this.A=value;
return this as TClass;
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
public int B {get ; set; }
public DerivedClass SetPropertyB(int value)
{
this.B=value;
return this;
}
}
Then if you have some other derived classes, each of them can use the base SetPropertyA knowing the return value is of type of itself.
I want to force my child classes to pass themselves as as the generic parameter to the parent class.
For example :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
Obviously the above code won't compile. I'll restate : I want the child class to pass itself as the generic parameter and not any other child of BaseClass.
(The above code is kind of a psuedo code and will still not compile).
You can do this:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
But this doesn't force you to use ChildClass as the generic parameter. You could do this public class OtherChildClass : BaseClass<ChildClass> { } which would break the "coontract" that you want to enforce.
The direct answer is that if your accessing a static method then typeof(T) will give you the type for reflection.
However, there is probably better solutions than using reflection. Options:
1) Static constructor on the child class.
2) Abstract method declared in the base class.
I do not know the application, but I get concerned about my design if I feel like using a static constructor, I also get concerned if a base class needs to initialize the child class.
I suggest looking at injection as a solution rather than inheritance. It offers superior unit testing and often a better architecture.
More info (after initial post), this is my preferred solution:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
Hope this helps
The ConcurrentDictionary is being used as a Set<Type>. We can check in the Set<Type> if the type has been initialized. If not we run RegisterType on the type.
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
There are several inefficiencies with this pattern though.
object.GetType() is pretty darn slow, and inefficient.
Even with the HashSet behavior, we are checking for initialization on each instanciation. Its as fast as I can get it, but its still pretty superfluous.
I often use the class-factory pattern whereby a class has a private constructor and a static method to create the class. This allows for the situation where the class cannot be constructed for some reason, and a null is returned - very handy.
I would like to be able to extend this to a factory method which creates a particular class from a hierarchy of derived classes depending on conditions. However I can't see a way of then hiding the constructors of the derived classes to force the use of the factory method. If the factory method is in the base class it no longer has access to the private constructors of derived classes. Putting a factory method in every derived class doesn't work as the required type must then be known beforehand. Nested classes might be a way if a class had access to the private members of a nested class, but sadly it seems that the nested classes have access to the private members of the enclosing class, but not the other way round.
Does anyone know of a way of doing this?
There are several possibilities, two of which are:
Put all those classes in one project and make the constructors internal. Other projects won't be able to call those constructors but the code inside that project can.
Make the constructors of those classes protected (instead of private) and create a private derived class in the class containing the factory method. Create an instance of that private class and return it.
Example for the second option:
public static class AnimalFactory
{
public static Animal Create(int parameter)
{
switch(parameter)
{
case 0:
return new DogProxy();
case 1:
return new CatProxy();
default:
throw new ArgumentOutOfRangeException("parameter");
}
}
private class DogProxy : Dog { }
private class CatProxy : Cat { }
}
public abstract class Animal { }
public class Dog : Animal
{
protected Dog() { }
}
public class Cat : Animal
{
protected Cat() { }
}
Here's the sample code I was working on when Daniel posted his answer. It looks like it's doing what he suggested:
public static class BaseFactory
{
public static Base Create(bool condition)
{
if (condition)
{
return Derived1.Create(1, "TEST");
}
else
{
return Derived2.Create(1, DateTime.Now);
}
}
}
public class Base
{
protected Base(int value)
{
}
protected static Base Create(int value)
{
return new Base(value);
}
}
public sealed class Derived1: Base
{
private Derived1(int value, string text): base(value)
{
}
internal static Derived1 Create(int value, string text)
{
return new Derived1(value, text);
}
}
public sealed class Derived2: Base
{
private Derived2(int value, DateTime time): base(value)
{
}
internal static Derived2 Create(int value, DateTime time)
{
return new Derived2(value, time);
}
}
[EDIT] And for Daniel's second suggestion:
public static class BaseFactory
{
public static Base Create(bool condition)
{
if (condition)
{
return new Derived1Creator(1, "TEST");
}
else
{
return new Derived2Creator(1, DateTime.Now);
}
}
private sealed class Derived1Creator: Derived1
{
public Derived1Creator(int value, string text): base(value, text)
{
}
}
private sealed class Derived2Creator: Derived2
{
public Derived2Creator(int value, DateTime time): base(value, time)
{
}
}
}
public class Base
{
protected Base(int value)
{
}
protected static Base Create(int value)
{
return new Base(value);
}
}
public class Derived1: Base
{
protected Derived1(int value, string text): base(value)
{
}
protected static Derived1 Create(int value, string text)
{
return new Derived1(value, text);
}
}
public class Derived2: Base
{
protected Derived2(int value, DateTime time): base(value)
{
}
protected static Derived2 Create(int value, DateTime time)
{
return new Derived2(value, time);
}
}
Note that this second approach means that the classes can't be sealed, unfortunately.
Rather than using methods inside the class itself as a factory implement the Factory pattern by means of a static class ("the factory") that returns the correct instance based on the logic you write.
You can intercept the derived type creation in the base class contructor and check that the caller is your factory using StackFrames:
protected Class1() //base class ctor
{
StackFrame[] stackFrames = new StackTrace().GetFrames();
foreach (var frame in stackFrames)
{
//check caller and throw an exception if not satisfied
}
}