Domanda

Ho creato una classe factory chiamato AlarmFactory come tale ...

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    }
allarme

Heartbeat è derivato da allarme. Sto ottenendo un errore di compilazione "non può convertire implicitamente il tipo ... Esiste una conversione esplicita (che le manca un cast?)". Come faccio a impostare questa funzione per restituire un tipo derivato?

Modifica

Grazie a tutti per le vostre risposte. Ho sistemato l'errore di compilazione in pochi minuti dieci che è il motivo per cui non ho postato l'intero errore. Ma ho apprezzato i diversi approcci che sono stati menzionati.

Per la cronaca era "Impossibile convertire implicitamente il tipo 'goAlarmsCS.HeartbeatAlarm' a 'goAlarmsCS.Alarm' Esiste una conversione esplicita (che le manca un cast?)". (Credo). L'errore è stato che si verificano sulla linea 8.

Seth

È stato utile?

Soluzione

Di seguito è una soluzione che include una funzione specifica GetHeartbeatAlarm per recuperare un oggetto HeartbeatAlarm così come una funzione GetAlarm generica per restituire un allarme cui tipo è determinato dal parametro generico. In fondo c'è qualche esempio di codice che mostra come questo possa essere chiamato:

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);
    }
}

Altri suggerimenti

La cosa migliore sarebbe quella di fare Alarm un'interfaccia, o se questo non è possibile, creare un'interfaccia IAlarm, ed ereditare da questa interfaccia sia per Alarm e HeartbeatAlarm.

AlarmFactory.GetAlarm deve restituire un'istanza IAlarm. Analogamente, HeartbeatAlarm.GetAlarm() dovrebbe restituire un'istanza IAlarm.

Questo dovrebbe eliminare eventuali errori di compilazione, più il vantaggio è che tutte le relazioni sono in modo pulito contrattuale, che dovrebbe rendere il codice che molto più futuro-friendly.

Hai provato ciò che suggerisce il compilatore?

return (Alarm) alarm;

Modifica:. Questo è completamente sbagliato, ma sto lasciando questa risposta qui per preservare la discussione nei commenti

Come qualcuno ha già suggerito, un ridondante Interface è un modo semplice per ottenere questo risultato. Mi sembra un esempio pulito potrebbe aiutare i futuri visitatori ..

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top