mercredi 20 janvier 2021

Confused how to link generic base classes together

I am trying to setup a component and registration system using generics but I am finding generics very confusing to setup, i don't understand how to structure the generics setup so it will actually work correctly!

This is my registration controller, it takes in a component that registers to it and puts it to a hash set:

public interface IRegisterControl<T>
{
    void Register(T register);
    void DeRegister(T register);
}
public abstract class RegistrationController<T> : IRegisterControl<T> where T : IRegister
{
    protected readonly HashSet<T> _entities = new HashSet<T>();
    public void Register(T iRegister) => _entities.Add(iRegister);
    public void DeRegister(T iRegister) => _entities.Remove(iRegister);
}

A derived class such as an animator below derives from the registration controller and does what ever it needs to do with the entities for what ever type:

public class AnimationController : RegistrationController<IAnimate>
{
    public void StartAllAnimations()
    {
        foreach (var anim in _entities)
            anim.LoadAnimation();            
    }
    public void StopAllAnimations()
    {
        foreach (var anim in _entities)
            anim.UnLoadAnimation();            
    }
}

This compiles fine, but the problem I have is how I setup my objects that want to be registered. They inherit a base class which is also generic and which handles the registration process:

public abstract class RegistrationComponent<T> : IRegister where T : IRegisterControl<T>
{
    //this should get the controller T and register itself as IRegister
    public void Init() => FindComponent<T>().Register(this);
    public void OnDestroy()=> FindComponent<T>().DeRegister(this);
}

This RegistrationComponent class gives an error for the functions when i pass in this:

Cannot convert from Entities.RegistrationComponent<T> to T

And an example script derived from this:

public interface IRegister {}
public interface IAnimate : IRegister
{
    void LoadAnimation();
    void UnLoadAnimation();
}
public class ProgressBar : RegistrationComponent<AnimationController>, IAnimate
{
        // the init function in base should do the following:
        // get component of AnimationController
        // then register itself as IRegister

        public void LoadAnimation() { }
        public void UnLoadAnimation() { }
}

However I get this error for my class declaration as well:

The type 'Entities.AnimationController' cannot be used as type parameter 'T' in the generic type or
method 'RegistrationComponent<T>'. There is no implicit reference conversion from 
Entities.AnimationController' to 
Entities.Interfaces.IRegisterControl<Entities.AnimationController>'.

I'm out of ideas at this point on how to get this to work properly, so am hoping some one can explain how this is done with generics.

Aucun commentaire:

Enregistrer un commentaire