2010-06-02 21 views
0

我創建了一個叫做AlarmFactory因爲這樣的工廠類...你如何使一個可以返回派生類型的工廠?

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 } 

心跳警報是從報警的。我得到一個編譯錯誤「不能隱式轉換類型...存在顯式轉換(你是否缺少一個轉換?)」。我如何設置它以返回派生類型?

編輯

謝謝大家對你的答案。我在十分鐘內解決了編譯錯誤,這就是爲什麼我沒有發佈整個錯誤。但我讚賞所提到的不同方法。

對於記錄它是「不能隱式轉換類型'goAlarmsCS.HeartbeatAlarm'到'goAlarmsCS.Alarm'顯式轉換存在(您是否缺少演員?)」。 (我認爲)錯誤發生在上線8

賽斯

+0

請發佈整個編譯器錯誤+告訴我們你得到它的哪一行。 – 2010-06-02 19:27:04

+3

如果HeartbeatAlarm確實是從警報派生的,那麼您應該能夠毫無錯誤地返回它。我們可能需要查看更多的代碼和有關編譯器錯誤的更多詳細信息,包括行,才能提供幫助。 – GBegen 2010-06-02 19:28:05

+0

HeartbeatAlarm.GetAlarm()返回什麼:報警類型還是HeartbeatAlarm類型?我猜這是其中越來越觸發編譯時錯誤(從報警向下轉換 - > HeartbeatAlarm,當然) – code4life 2010-06-02 19:31:12

回答

4

下面是包含特定GetHeartbeatAlarm函數來檢索一個HeartbeatAlarm對象以及一個通用GetAlarm函數返回報警其類型由通用參數確定的溶液。在底部有證據顯示這是如何會被稱爲一些示例代碼:

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

非常感謝您的詳盡解答。賽斯 – 2010-06-02 20:51:47

0

你試過編譯器暗示什麼?

return (Alarm) alarm; 

編輯:這是完全錯誤的,但我留下這個答案在這裏保留評論中的討論。

+0

該行在沒有upcast的情況下編譯正常。 – code4life 2010-06-02 19:37:52

+0

對不起,我只是在學習c#。如果我想要返回派生類型,該怎麼辦?不會投射到(警報)會返回一種警報而不是HeartbeatAlarm? Seth – 2010-06-02 19:42:54

+0

@Seth,您的返回類型是Alarm,返回的對象將會在有或沒有演員時發出警報。如果您想顯式使用派生類型,則必須在收到對象後將其轉換爲派生類型。類似DerivedAlarm警報=(DerivedAlarm)AlarmFactory.GetAlarm(AlarmTypes.DerivedAlarm); – 2010-06-02 19:52:32

3

你最好的選擇將是使Alarm的界面,但如果這是不可能的,創建一個IAlarm接口,從這個接口既AlarmHeartbeatAlarm繼承。

AlarmFactory.GetAlarm應該返回一個IAlarm實例。同樣,HeartbeatAlarm.GetAlarm()應該返回一個IAlarm實例。

這將消除任何編譯器錯誤,加上好處是,所有的關係都是乾淨的合同,這應該使代碼更未來的友好。

+0

我的印象是'HeartbearAlarm'和'Alarm'是石英類型,儘管我從來沒有使用Quartz。 – Powerlord 2010-06-02 20:00:08

+0

他們不是石英類型......雖然我在這個項目中使用石英。 – 2010-06-02 20:02:42

0

正如一些已經表明,一個多餘的接口是實現這個簡單的方法。看起來像一個乾淨的例子可能會幫助未來的遊客..

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); 
相關問題