nawfal
nawfal

Reputation: 73253

Expose constructor only to base class, possible?

public class Base<S>
{
    public static Derived<S, T> Create<T>()
    {
        return new Derived<S, T>(); //if not public, I wont get it here.
    }
}

public class Derived<S, T> : Base<S>
{
    public Derived() //the problem, dont want it public
    {

    }
}

This is the basic structure I have got.

Requirements:

1) I don't want an instance of Derived<,> to be constructed calling Derived<,> class at all, be it via constructor or a static method. I want it to be created only via Base<>. So this is out:

public class Derived<S, T> : Base<S>
{
    Derived()
    {

    }

    public static Derived<S, T> Create()
    {
        return new Derived<S, T>();
    }
}

2) Derived<,> class itself must be public (which means I can't private nest Derived<,> inside Base<>). Only then I can return Derived<,> from the static Create method in Base<>.

Is it possible?

Upvotes: 1

Views: 423

Answers (4)

nawfal
nawfal

Reputation: 73253

I achieved my requirement this way:

public abstract class Base<S>
{
    public static Derived<S, T> Create<T>() 
    {
        return new ReallyDerived<S, T>(); 
    }



    class ReallyDerived<T> : Derived<S, T>
    {
        public ReallyDerived()
        {

        }
    }
}

public abstract class Derived<S, T> : Base<S>
{

}

Now this works..

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502696

I would declare a public interface, and make the implementation private within Base:

public class Base<S>
{
    public static IFoo<S, T> Create<T>()
    {
        return new Derived<T>(); //if not public, I wont get it here.
    }

    // Only generic in T, as we can use S from the containing class
    private class Derived<T> : Base<S>, IFoo<S, T>
    {
        public Derived()
        {
            ...
        }
    }
}

public interface IFoo<S, T>
{
    // Whatever members you want
}

Upvotes: 0

iamkrillin
iamkrillin

Reputation: 6876

Reflection!

void Main()
{
    Derived dr = Base.GetDerived<Derived>();
}

public class Base
{
    public int ID { get; set; }
    public Base()
    {

    }

    public static T GetDerived<T>() where T : Base
    {
        T toReturn = (T)typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null).Invoke(null);
        return toReturn;
    }

}

public class Derived : Base
{
    private Derived()
    {

    }
}

Upvotes: 1

p.s.w.g
p.s.w.g

Reputation: 149050

You can make the derived class's constructor internal as in

public class Base<S>
{
    public static Derived<S, T> Create<T>()  // visible externally
    {
        return new Derived<S, T>(); 
    }
}

public class Derived<S, T> : Base<S>
{
    internal Derived() // not visible outside the current assembly
    {

    }
}

Upvotes: 3

Related Questions