Pregunta

He creado una clase de fábrica llamada AlarplFactory como tal ...

1    class AlarmFactory
2    {
3        public static Alarm GetAlarm(AlarmTypes alarmType)  //factory ensures that correct alarm is returned and right func pointer for trigger creator.
4        {
5            switch (alarmType)
6            {
7                case AlarmTypes.Heartbeat:
8                    HeartbeatAlarm alarm = HeartbeatAlarm.GetAlarm();
9                    alarm.CreateTriggerFunction = QuartzAlarmScheduler.CreateMinutelyTrigger;
10                    return alarm;
11
12                   break;
13                default:
14                
15                    break;
16            }
17        }
18    }

La alarma del corazón se deriva de la alarma. Estoy recibiendo un error de compilación "No puedo convertir implícitamente el tipo ... una conversión explícita existe (¿te estás perdiendo un elenco?)". ¿Cómo configuro esto para devolver un tipo derivado?

EDITAR

GRACIAS A TODOS POR SUS RESPUESTAS O COMENTARIOS. Se arreglé el error de compilación en diez minutos, por lo que no publiqué todo el error. Pero aprecié los diferentes enfoques que se mencionaron.

Para el registro, era "no puede convertir implícitamente el tipo 'Goalarmscs.HeartBeatAlm' a 'Goalarmsc.Alarm' Existe una conversión explícita (¿te estás perdiendo un elenco?)". (Creo.) El error estaba ocurriendo en la línea 8.

Seth

¿Fue útil?

Solución

A continuación se muestra una solución que incluye una función específica de GetheartBeatAmarm para recuperar un objeto HeartBeatAmarm, así como una función genérica GetALARM para devolver una alarma cuyo tipo está determinado por el parámetro genérico. En la parte inferior hay algún código de ejemplo que muestra cómo se llamaría:

enum AlarmTypes
{
    Heartbeat,
    AnotherAlarm,
    // ...
}

delegate void CreateTriggerDelegate();

class Alarm
{
    // ...

    public CreateTriggerDelegate CreateTriggerFunction { get; set; }
}

class HeartbeatAlarm : Alarm
{
    // ...

    public static HeartbeatAlarm GetAlarm()
    {
        return new HeartbeatAlarm();
    }
}

class QuartzAlarmScheduler
{
    public static CreateTriggerDelegate CreateMinutelyTrigger { get; set; }
}

class AlarmFactory
{
    public static Alarm GetAlarm(AlarmTypes alarmType)  //factory ensures that correct alarm is returned and right func pointer for trigger creator.
    {
        switch (alarmType)
        {
            case AlarmTypes.Heartbeat:
                return GetHeartbeatAlarm();
            default:
                throw new ArgumentException("Unrecognized AlarmType: " + alarmType.ToString(), "alarmType");
        }
    }

    static Alarm _GetAlarm<T>()
        where T : Alarm
    {
        Type type = typeof(T);
        if (type.Equals(typeof(HeartbeatAlarm)))
            return GetHeartbeatAlarm();
        else
            throw new ArgumentException("Unrecognized generic Alarm argument: " + type.FullName, "T");
    }

    public static T GetAlarm<T>()
        where T : Alarm
    {
        return (T)_GetAlarm<T>();
    }

    public static HeartbeatAlarm GetHeartbeatAlarm()
    {
        HeartbeatAlarm alarm = HeartbeatAlarm.GetAlarm();
        alarm.CreateTriggerFunction = QuartzAlarmScheduler.CreateMinutelyTrigger;
        return alarm;
    }
}

class Example
{
    static void GetAlarmExamples()
    {
        HeartbeatAlarm alarm;

        alarm = AlarmFactory.GetHeartbeatAlarm();

        alarm = AlarmFactory.GetAlarm<HeartbeatAlarm>();

        alarm = (HeartbeatAlarm)AlarmFactory.GetAlarm(AlarmTypes.Heartbeat);
    }
}

Otros consejos

Tu mejor opción sería hacer Alarm una interfaz, o si eso no es posible, cree un IAlarm interfaz y heredar de esta interfaz para ambos Alarm y HeartbeatAlarm.

AlarmFactory.GetAlarm Debería devolver un IAlarm instancia. Igualmente, HeartbeatAlarm.GetAlarm() Debería devolver un IAlarm instancia.

Esto debería eliminar cualquier error del compilador, además de la ventaja es que todas las relaciones son limpiamente contractuales, lo que debería hacer que el código sea mucho más amigable para el futuro.

¿Has probado lo que sugiere el compilador?

return (Alarm) alarm;

Editar: Esto está completamente mal, pero dejo esta respuesta aquí para preservar la discusión en los comentarios.

Como algunos ya han sugerido, una interfaz redundante es una manera fácil de lograr esto. Parece un ejemplo limpio podría ayudar a los futuros visitantes.

public interface IAlarm
{
    public int bpm { get; set; }    // declared base props
}

public class Alarm : IAlarm
{
    public int bpm { get; set; }    // implemented base props
}

public class HeartbeatAlarm : Alarm
{
    public int min { get; set; }    // extended type specific props
}

public class FactoryMethods
{
    public static T AlarmFactory<T>(int bpm) where T : IAlarm, new()
    {
        // interfaces have no constructor but you can do this
        T alarm = new T() {
            bpm = bpm
        };

        return alarm;
    }
}

// C# will automagically infer the type now..
HeartbeatAlarm heartbeatAlarm = FactoryMethods.AlarmFactory<HeartbeatAlarm>(40);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top