Let's say I have a helper class like
public class Selection<T, W> : ISelection<T,W> where W : ICollection<T>
{
public Selection(Func<W> selectableItemsProvider)
{
...
}
}
As C# does not support delegating interface implementation, I thought I'd save myself a bit of boilerplate and just extend the Selection class...
public class MyFoo : Selection<Blah, List<Blah>>
{
private List<Blah> _blahs = new List<Blah>();
public MyFoo() : base(() => _blahs)
{
...
}
}
Except I cannot do that, can I, because
Cannot access non-static property '_blahs' in static context
even though I already know the provider won't be invoked until after object construction.
Is there a way around this or am I stuck with adding boilerplate code?
One somewhat roundabout way to do this is to pass a lambda that returns the same list every time to the base class constructor. Then call that lambda to initialise blahs:
public class Selection<T, W>: ISelection<T, W> where W : ICollection<T> {
// assuming you have a property like this that is initialised by the constructor...
protected Func<W> SelectableItemsProvider { get; }
public Selection(Func<W> selectableItemsProvider)
{
SelectableItemsProvider = selectableItemsProvider;
}
}
public class MyFoo : Selection<Blah, List<Blah>>
{
private List<Blah> _blahs;
public MyFoo() : base(new List<Blah>().CaptureInFunc())
{
_blahs = SelectableItemsProvider();
}
}
CaptureInFunc is an extension method declared like this:
public static Func<T> CaptureInFunc<T>(this T t) => () => t;
This gives us a lambda that returns t every time.
One approach might be to first introduce base abstract class. This class will hold all the logic:
public abstract class SelectionBase<T, W> where W : ICollection<T>
{
protected SelectionBase() {
}
protected abstract Func<W> GetSelectableItemsProvider();
}
Then change your current Selection to inherit from it and accept selector in constructor, that's the whole implementation:
public sealed class Selection<T, W> : SelectionBase<T, W> where W: ICollection<T> {
private readonly Func<W> _selectableItemsProvider;
public Selection(Func<W> selectableItemsProvider) {
_selectableItemsProvider = selectableItemsProvider;
}
protected override Func<W> GetSelectableItemsProvider() {
return _selectableItemsProvider;
}
}
Now if you want to extend selection in a way mentioned in your question:
public class SpecificSelection : SelectionBase<string, List<string>> {
private List<string> _blah;
public SpecificSelection() {
}
protected override Func<List<string>> GetSelectableItemsProvider() {
return () => _blah;
}
}
You can't refer to members of 'this' in the call to a base constructor because 'this' does not exist yet.
I suggest composition instead of inheritance. The class may still implement the same interface as the helper and then delegate all calls to the real implementation.
public class MyFoo : ISelection<Blah, List<Blah>>
{
private List<Blah> _blahs;
private ISelection<Blah, List<Blah>> _implementation;
public MyFoo()
{
_blahs = new List<Blah>();
_implementation = new Selection<Blah, List<Blah>>(() => _blahs);
}
public void DoSomethingWithSelection()
{
_implementation.DoSomethingWithSelection();
}
}
Related
I have the following classes
public abstract class BaseViewPresenter { }
public abstract class BaseView<T> : UserControl
where T : BaseViewPresenter { }
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> { }
I have a method that looks like this (simplified)
public BaseView<BaseViewPresenter> Resolve(BaseViewPresenter model)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
// Correctly creates BaseView object
var control = Activator.CreateInstance(viewType);
// Fails to cast as BaseView<BaseViewPresenter> so returns null
return control as BaseView<BaseViewPresenter>;
}
When I call this using an instances of LoginPresenter
var login = new LoginPresenter();
var ctl = Resolve(login);
The line Activator.CreateInstance(viewType) correctly resolves into a new instances of my LoginView, however control as BaseView<BaseViewPresenter> can't do the cast correctly so returns null.
Is there a way to correctly cast the control into BaseView<BaseViewPresenter> without using specific type generics?
Since LoginView inherits from BaseView<LoginPresenter>, and LoginPresenter inherits from BaseViewPresenter, I would assume there's a way to convert LoginView to BaseView<BaseViewPresenter>.
I am stuck with using .Net 3.5
This is a very frequently asked question. Let's rename your types:
abstract class Fruit { } // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { } // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> { } // was LoginView
Your question now is:
I have a BowlOfApples, which inherits from FruitBowl<Apple>. Why can I not use it as a FruitBowl<Fruit>? An apple is a fruit, so a bowl of apples is a bowl of fruit.
No, it isn't. You can put a banana in a bowl of fruit, but you can't put a banana in a bowl of apples, and therefore a bowl of apples is not a bowl of fruit. (And by similar argument, a bowl of fruit is not a bowl of apples either.) Since the operations you can legally perform on the two types are different, they cannot be compatible.
Here is a photo of StackOverflow legend Jon Skeet demonstrating this fact:
The feature you want is called generic contravariance, and it is supported only on interfaces and delegate types when the compiler can prove that the variance is safe, and when the varying type is a reference type. For example, you can use an IEnumerable<Apple> in a context where IEnumerable<Fruit> is needed because the compiler can verify that there is no way that you can put a Banana into a sequence of fruit.
Do a search on "C# covariance and contravariance" on this site or on the web and you'll find many more details about how this feature works. In particular, my series of articles on how we designed and implemented this feature in C# 4 starts here: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
I accepted Eric's answer since it provides a great explanation of why what I wanted wasn't possible, but I also thought I'd share my solution in case anyone else runs into this same problem.
I removed the generic type parameter from my original BaseView class, and created a 2nd version of the BaseView class that included the generic type parameter and specifics for it.
The first version is used by my .Resolve() method or other code that doesn't care about the specific types, and the second version is used by any code that does care, such as the implentation of a BaseView
Here's an example of how my code ended up looking
// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl
{
public BaseViewPresenter Presenter { get; set; }
}
public abstract class BaseView<T> : BaseView
where T : BaseViewPresenter
{
public new T Presenter
{
get { return base.Presenter as T; }
set { base.Presenter = value; }
}
}
// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter>
{
// Can now call things like Presenter.LoginPresenterMethod()
}
// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
BaseView view = Activator.CreateInstance(viewType) as BaseView;
view.Presenter = presenter;
return view;
}
You're expecting to treat the type as being covariant with respect to the generic argument. Classes can never be covariant; you'd need to use an interface rather than (or in addition to) an abstract class to make it covariant with respect to T. You'd also need to be using C# 4.0.
My usual solution to this problem is to create an intermediary class that has access to the type-parametric class's methods through delegates. Fields can also be accessed through getters/setters.
The general pattern goes:
public abstract class Super {}
public abstract class MyAbstractType<T> where T : Super {
public MyGeneralType AsGeneralType() {
return MyGeneralType.Create(this);
}
// Depending on the context, an implicit cast operator might make things
// look nicer, though it might be too subtle to some tastes.
public static implicit operator MyGeneralType(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
public int field;
public void MyMethod1() {}
public void MyMethod2(int argument) {}
public abstract bool MyMethod3(string argument);
}
public delegate T Getter<T>();
public delegate void Setter<T>(T value);
public delegate void MyMethod1Del();
public delegate void MyMethod2Del(int argument);
public delegate bool MyMethod3Del(string argument);
public class MyGeneralType {
public Getter<int> FieldGetter;
public Setter<int> FieldSetter;
public MyMethod1Del MyMethod1;
public MyMethod2Del MyMethod2;
public MyMethod3Del MyMethod3;
public static MyGeneralType Create<T>(MyAbstractType<T> t) where T : Super {
var g = new MyGeneralType();
g.FieldGetter = delegate { return t.field; };
g.FieldSetter = value => { t.field = value; };
g.MyMethod1 = t.MyMethod1;
g.MyMethod2 = t.MyMethod2;
g.MyMethod3 = t.MyMethod3;
return g;
}
public int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
The above exemplifies getting all the methods and fields but normally I only need a few of them. This is a general solution to the problem and one could feasibly write a tool to generate these intermediary classes automatically, which I might at some point.
Try it here: https://dotnetfiddle.net/tLkmgR
Note that this is enough for all my cases, but you can be extra hacky with this:
public abstract class MyAbstractType<T> where T : Super {
// ... Same everything else ...
// data fields must become abstract getters/setters, unfortunate
public abstract int field {
get;
set;
}
public static implicit operator MyAbstractType<Super>(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
}
public class MyGeneralType : MyAbstractType<Super> {
// ... same constructors and setter/getter
// fields but only keep method fields
// that contain the method references for
// implementations of abstract classes,
// and rename them not to clash with the
// actual method names ...
public MyMethod3Del myMethod3Ref;
// Implement abstract methods by calling the corresponding
// method references.
public override bool MyMethod3(string argument) {
return myMethod3Ref(argument);
}
// Same getters/setters but with override keyword
public override int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
And there you go, now you can literally cast a MyAbstractType<Sub> where Sub : Super to a MyAbstractType<Super>, although it's no longer the same object anymore, but it does retain the same methods and data, it's sort of a complex pointer.
public class Sub : Super {}
public class MySubType : MyAbstractType<Sub> {
public int _field;
public override int field {
get { return _field; }
set { _field = value; }
}
public override bool MyMethod3(string argument) {
Console.WriteLine("hello " + argument);
return argument == "world";
}
}
public class MainClass {
public static void Main() {
MyAbstractType<Sub> sub = new MyAbstractType<Sub>();
MyAbstractType<Super> super = sub;
super.MyMethod3("hello"); // calls sub.MyMethod3();
super.field = 10; // sets sub.field
}
}
This isn't as good in my opinion, the other version of MyGeneralType is a more straighforward layer over the concrete types, plus it doesn't require rewriting the data fields, but it does actually answer the question, technically. Try it here: https://dotnetfiddle.net/S3r3ke
Example
Using these abstract classes:
public abstract class Animal {
public string name;
public Animal(string name) {
this.name = name;
}
public abstract string Sound();
}
public abstract class AnimalHouse<T> where T : Animal {
List<T> animals;
public AnimalHouse(T[] animals) {
this.animals = animals.ToList();
}
public static implicit operator GeneralAnimalHouse(AnimalHouse<T> house) {
return GeneralAnimalHouse.Create(house);
}
public List<string> HouseSounds() {
return animals.Select(animal => animal.Sound()).ToList();
}
}
We make this "general" variant:
public delegate List<string> HouseSoundsDel();
public class GeneralAnimalHouse {
public HouseSoundsDel HouseSounds;
public static GeneralAnimalHouse Create<T>(AnimalHouse<T> house) where T : Animal {
var general = new GeneralAnimalHouse();
general.HouseSounds = house.HouseSounds;
return general;
}
}
And finally with these inheritors:
public class Dog : Animal {
public Dog(string name) : base(name) {}
public override string Sound() {
return name + ": woof";
}
}
public class Cat : Animal {
public Cat(string name) : base(name) {}
public override string Sound() {
return name + ": meow";
}
}
public class DogHouse : AnimalHouse<Dog> {
public DogHouse(params Dog[] dogs) : base(dogs) {}
}
public class CatHouse : AnimalHouse<Cat> {
public CatHouse(params Cat[] cats) : base(cats) {}
}
We use it like this:
public class AnimalCity {
List<GeneralAnimalHouse> houses;
public AnimalCity(params GeneralAnimalHouse[] houses) {
this.houses = houses.ToList();
}
public List<string> CitySounds() {
var random = new Random();
return houses.SelectMany(house => house.HouseSounds())
.OrderBy(x => random.Next())
.ToList();
}
}
public class MainClass {
public static void Main() {
var fluffy = new Cat("Fluffy");
var miu = new Cat("Miu");
var snuffles = new Cat("Snuffles");
var snoopy = new Dog("Snoopy");
var marley = new Dog("Marley");
var megan = new Dog("Megan");
var catHouse = new CatHouse(fluffy, miu, snuffles);
var dogHouse = new DogHouse(snoopy, marley, megan);
var animalCity = new AnimalCity(catHouse, dogHouse);
foreach (var sound in animalCity.CitySounds()) {
Console.WriteLine(sound);
}
}
}
Output:
Miu: meow
Snoopy: woof
Snuffles: meow
Fluffy: meow
Marley: woof
Megan: woof
Notes:
I added names so it's clear that the method references carry their owner's data with them, for those unfamiliar with delegates.
The required using statements for this code are System, System.Collections.Generic, and System.Linq.
You can try it here: https://dotnetfiddle.net/6qkHL3#
A version that makes GeneralAnimalHouse a subclass of AnimalHouse<Animal> can be found here: https://dotnetfiddle.net/XS0ljg
I have problem.
For example, considering these 4 classes.
public abstract ParentContainer<T> where T: Parentfoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainer : ParentContainer<ChildFoo>
{
}
public abstract class ParentFoo
{
public string name;
}
public class ChildFoo : ParentFoo
{
}
How can I write a method which accepts a List of any arbitrary ChildContainers as a parameter,
which do operation on their fooLists?
Is it even possible?
Additional Explanation, there are many different childs of ParentContainer,
each with a List of a different child of foo.
public class ChildContainerB : ParentContainer<ChildFooB>{}
public class ChildContainerC : ParentCOntainer<ChildFooC>{}
...
public class ChildFooB : ParentFoo;
public class ChildFooC : ParentFoo;
Then I need a method something like this
//X means it can be any arbitrary ChildContainer
public void method(List<ChilContainerX> list)
{
foreach(ChildContainerX x in list)
{
print(x.fooList.Last().name);
}
}
So what you are asking isn't possible because you need a concrete type for the List<>. There are a couple of workarounds though.
Use List<object>. This is obviously not great because as it means you lose type checking completely and could end up with anything being added to the list. So for that reason, I wouldn't recommend this approach.
Make ParentContainer<> implement a marker interface. For example:
public interface IParentContainer
{
}
public abstract class ParentContainer<T> : IParentContainer
where T: ParentFoo
{
//snip
}
And now you can have your list like this:
var containers = new List<IParentContainer>
{
new ChildContainer(),
new ChildContainer2()
};
Unless I misunderstand the question, you want something like this ...
public void DoStuffWith<T>(List<ParentContainer<T>> containers) where T : Parentfoo
{
//TODO: implement
}
This would work on objects of type ...
List<ParentContainer<ParentFoo>>
List<ParentContainer<ChildFoo>>
where ChildFoo : ParentFoo
and solves the issue of "List<ParentContainer<ParentFoo>> does not implement IEnumerable<ParentContainer<ChuldFoo>>" which I suspect is the compiler you are seeing.
Taking this a step further something like ....
public void DoStuffWith<ContainerT,ElementT>(List<ContainerT<ElementT>> containers)
where ContainerT : ParentContainer
where ElementT : Parentfoo
{
//TODO: implement
}
... likely over complicates the issue but i suspect is what you are trying to achieve.
At this point I would question the data structures you have and give them some common parent for example ...
public class ParentContainer<T> : IEnumerable<T> { ... }
public class ChildContainer<T> : ParentContainer<T>, IEnumerable<T> { ... }
Since both implement IEnumerable you can now do ...
public void DoStuffWith<T>(IEnumerable<T> containers) where T : ParentFoo
{
//TODO: implement
}
This avoids the need to be concerned with the collection type at all.
class Program
{
static void Main(string[] args)
{
List<ParentContainer<ChildFoo>> ca = new List<ParentContainer<ChildFoo>>();
ProcessContainers processor = new ProcessContainers();
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerB { fooList = new List<ChildFoo>() });
processor.Process(ca);
}
}
public abstract class ParentContainer<T> where T: ParentFoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainerA : ParentContainer<ChildFoo>
{
}
public class ChildContainerB : ParentContainer<ChildFoo>
{
}
public class ProcessContainers
{
public void Process<T>(List<ParentContainer<T>> childContainers) where T : ParentFoo
{
foreach(var item in childContainers)
{
foreach(var foo in item.fooList)
{
foo.Porcess();
}
}
}
}
public abstract class ParentFoo
{
public string name;
public abstract void Porcess();
}
public class ChildFoo : ParentFoo
{
public override void Porcess()
{
//Do some processing
}
}
My aim is to write an abstract base class which contains a method for deriving “child instances”. In this method already some computation is done which is common in all deriving classes.
The difficulty is that the base class is not able to create the child class on its own. So I introduced a type parameter T in my base class and a protected abstract method which shall return an instance of T.
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return NewInstanceFrom(param);
}
protected abstract T NewInstanceFrom(string param);
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative() { }
protected sealed override Derivative NewInstanceFrom(string param)
{
return new Derivative(param);
}
private Derivative(string param)
{
// some configuration
}
}
The disadvantage of this approach is that I cannot ensure that NewInstanceFrom is only invoked by the base class. It could also be invoked by classes inheriting from Derivative. That’s what I want to avoid.
So I could encapsulate the functionality in a private class or delegate:
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return subElementDerivator(param);
}
protected Base<T>(Func<string, T> subElementDerivator)
{
this.subElementDerivator = subElementDerivator;
}
private Func<string, T> subElementDerivator;
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative()
: base(deriveSubElement)
{
}
private Derivative(string param)
: base(deriveSubElement)
{
// some configuration
}
private static Derivative deriveSubElement(string param)
{
return new Derivative(param);
}
}
But this introduces a new object.
Is there a simpler way to prevent access to a functionality (which the base class shall have access to) from heirs of Derivative?
You can use explicit interface implementation to hide your factory method. Any client can still call the Create method after casting but at least intellisense won't help developers.
public interface ISecretFactory<T>
{
T Create(string param);
}
public abstract class Base<T> where T : Base<T>, ISecretFactory<T>
{
public T GetChild()
{
// We are sure type T always implements ISecretFactory<T>
var factory = this as ISecretFactory<T>;
return factory.Create("base param");
}
}
public class Derivative : Base<Derivative>, ISecretFactory<Derivative>
{
public Derivative()
{
}
private Derivative(string param)
{
}
Derivative ISecretFactory<Derivative>.Create(string param)
{
return new Derivative(param);
}
}
public class SecondDerivative : Derivative
{
public void F()
{
// intellisense won't show Create method here.
// But 'this as ISecretFactory<Derivative>' trick still works.
}
}
The additional object can be avoided by moving the ComplexComputation to the constructor of the base class and making the GetChild method abstract to let the deriving class pick a correct constructor there.
But how to return the computed value param in base constructor to the invoking derivate constructor? A possibility is to use the out parameter modifier. But because in C# 5.0 we are unfortunately not able to declare the variables before (or within) the base constructor call, we need to take the parameter along in the derivative constructor.
public abstract class Base<T> where T : Base<T>
{
public abstract T GetChild();
protected Base(T parent, out string param)
{
param = ComplexComputation();
}
protected Base()
{
}
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public sealed override Derivative GetChild()
{
string param;
return new Derivative(this, out param);
}
public Derivative() { }
private Derivative(Derivative parent, out string param)
: base(parent, out param)
{
// some configuration
}
}
In my case I could leave the param from the constructors away, instead I stored it in a public property.
This approach except the pesky necessary hack looks relatively clean to me, but it does not “scale” when multiple overloadings of GetChild are necessary.
Maybe in C# 6.0 it is possible to declare the param directly in the base constructor invocation. https://msdn.microsoft.com/de-de/magazine/dn683793.aspx
I had a question on C# generics. I wish to store a generic type variable in my abstract class without declaring that type outside the class.
Below is the code sample. Please note that I do not wish to make the Param classes exposed outside the Calc class.
Thanks in advance.
- Dutta.
abstract class Base { }
abstract class Calc<T> where T : Base
{
protected Param Member; /* how can this be a made a generic declaration
* WITHOUT declaring this class like,
* class Calc<T, P>
* where T : Base
* where P : Param */
protected Calc(Param p)
{
this.Member = p;
}
protected abstract class Param { }
}
class MyBase : Base { }
class MyCalc : Calc<MyBase>
{
public MyCalc() : base(new MyParam()) { }
public void doSomething()
{
base.Member.A++; // fails on compilation
}
private class MyParam : Calc<MyBase>.Param
{
public int A;
public MyParam() { this.A = 0; }
}
}
You just need to cast it to the new type, because no matter what, the variable Member was declared as Param and it will always be accessed as Param:
((MyParam)base.Member).A++;
Secondly, you can fix up your MyParam class by changing from this:
MyParam : Calc<MyBase>.Param
To this:
MyParam : Param
Because Param is already Calc<MyBase> through generics and inheritance.
Thraka's answer is correct: if you don't want to use generics you need to cast. Just to add to it, in case what you're really trying to do looks something like this. Here's a set of classes that you can expose from your library, which will not be extensible by clients (unless they're running with full trust and can use reflection etc.!!) but which can be used in a type-safe way.
public abstract class SupportedPaymentMethod
{
protected internal SupportedPaymentMethod() { }
}
public sealed class Check : SupportedPaymentMethod
{
public int CheckNumber { get; private set; }
public Check(int checkNumber)
: base()
{
CheckNumber = checkNumber;
}
}
public sealed class CreditCard : SupportedPaymentMethod
{
public CreditCard()
: base()
{ }
}
public abstract class Payment<T>
where T : SupportedPaymentMethod
{
public T Method { get; private set; }
protected internal Payment(T method)
{
Method = method;
}
}
public sealed CheckPayment : Payment<Check>
{
public CheckPayment(Check check)
: base(check)
{ }
}
public sealed CreditCardPayment : Payment<CreditCard>
{
public CreditCardPayment(CreditCard creditCard)
: base(creditCard)
{ }
}
Clients (i.e. code outside of your class library's assembly) will be able to instantiate a CheckPayment or a CreditCardPayment, but they will not be able to create a new class deriving from Payment<T>. So, it will not be possible for clients to create a CheatingPaymentMethod : Payment<Cheating>, for example. :)
Calls like your intended call to base.Member.A++ will now work:
var checkPayment = new CheckPayment(new Check(123456));
var checkNumber = checkPayment.Method.CheckNumber; // Success! :)
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#