Question

J'ai créé une classe d'usine appelée AlarmFactory en tant que telle ...

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    }

alarme Heartbeat est dérivé de l'alarme. Je reçois une erreur de compilation « ne peut pas convertir implicitement le type ... Il existe une conversion explicite (vous manque un casting?) ». Comment puis-je régler cela pour retourner un type dérivé?

EDIT

Merci à tous pour vos réponses. Je fixe l'erreur de compilation en quelques minutes dix qui est pourquoi je ne l'ai pas poster l'erreur tout. Mais j'ai apprécié les différentes approches qui ont été mentionnées.

Pour l'enregistrement, il était « Impossible de convertir implicitement le type « goAlarmsCS.HeartbeatAlarm » à « goAlarmsCS.Alarm » Une conversion explicite existe (vous manque un casting?) ». (Je pense). L'erreur se produisait sur la ligne 8.

Seth

Était-ce utile?

La solution

Ci-dessous, est une solution qui comprend une fonction de GetHeartbeatAlarm spécifique pour récupérer un objet HeartbeatAlarm ainsi que d'une fonction de GetAlarm générique pour retourner une alarme dont le type est déterminé par le paramètre générique. Au fond, il y a une projection de code exemple comment cela serait appelé:

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

Autres conseils

Votre meilleur pari serait de faire Alarm une interface, ou si ce n'est pas possible, créer une interface IAlarm, et hérite de cette interface pour les Alarm et HeartbeatAlarm.

AlarmFactory.GetAlarm doit retourner une instance de IAlarm. De même, HeartbeatAlarm.GetAlarm() doit retourner une instance de IAlarm.

Cela devrait éliminer toutes les erreurs du compilateur, plus l'avantage est que toutes les relations sont proprement contractuelles, ce qui devrait rendre le code plus beaucoup d'avenir de l'environnement.

Avez-vous essayé ce que le compilateur suggère?

return (Alarm) alarm;

Edit:. Ceci est complètement faux, mais je laisse cette réponse ici pour préserver la discussion dans les commentaires

Comme certains l'ont déjà suggéré, une interface redondante est un moyen facile d'y arriver. On dirait un visiteur exemple propre pourrait aider les futurs ..

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top