views:

113

answers:

1

I have the following abstract class design, I was wondering if anyone can suggest any improvements in terms of stronger enforcement of our requirements or simplifying implementing of the ControllerBase.

//Dependency Provider base
public abstract class ControllerBase<TContract, TType> where TType : TContract, class
{
    public static TContract Instance 
    {
        get { 
    return ComponentFactory.GetComponent<TContract, TType>(); 
            }
    }

 public TContract GetComponent<TContract, TType>() where TType : TContract, class
 {   
        component = (TType)Activator.CreateInstance(typeof(TType), true);
        RegisterComponentInstance<TContract>(component);
 }
}

//Contract
public interface IController
{
 void DoThing();
}

//Actual Class Logic
public class Controller: ControllerBase<IController,Controller>
{
 public void DoThing();

    //internal constructor
    internal Controller(){}

}


//Usage
public static void Main()
{
 Controller.Instance.DoThing();
}

The following facts should always be true,

  • TType should always implement TContract (Enforced using a generic constraint)

  • TContract must be an interface (Can't find a way to enforce it)

  • TType shouldn't have public constructor, just an internal one, is there any way to Enforce that using ControllerBase?

  • TType must be an concrete class (Didn't include New() as a generic constrain since the constructors should be marked as Internal)

A: 

There is a way to enforce TType being a concrete class and forbidding constructor success at the same time. I guess it might be possible to try to instantiate TType, which will succeed only if it is a concrete type, however, you want to avoid instantiation. I would suggest trying to throw an exception from the constructor. In your controller base, you can surround the instantiation with exception handling code. This will get through compile time only if you instantiate concrete type and it will get through runtime if you throw an exception... This is overall bad practice (if possible) and I guess you need totally different design to achive what are you looking for.

Gabriel Ščerbák