您如何制作可以返回派生类型的工厂?
-
23-10-2019 - |
题
我创建了一个称为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 }
心跳警报来自警报。我遇到了一个编译错误“无法隐式转换类型...存在明确的转换(您缺少演员?)。”我如何设置此设置以返回派生类型?
编辑
谢谢大家的答案。我在十分钟内修复了编译错误,这就是为什么我没有发布整个错误的原因。但是我感谢提到的不同方法。
作为记录,它是“不能隐式将类型的'grogarmscs.heartbeatalarm'转换为'grogarmscs.s.alarm'存在明确的转换(您是否缺少演员?)”。 (我认为)错误发生在第8行。
塞思
解决方案
下面是一个解决方案,其中包含特定的geartbeatAlarm函数,以检索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);
}
}
其他提示
最好的选择是 Alarm
接口,或者如果不可能,则创建一个 IAlarm
接口,并从此接口继承 Alarm
和 HeartbeatAlarm
.
AlarmFactory.GetAlarm
应该返回 IAlarm
实例。同样地, HeartbeatAlarm.GetAlarm()
应该返回 IAlarm
实例。
这应该消除任何编译器错误,再加上所有关系是所有关系都是干净的合同,这应该使代码变得更加友好。
您是否尝试过编译器的建议?
return (Alarm) alarm;
编辑:这是完全错误的,但是我在这里留下了这个答案,以保留评论中的讨论。
正如某些人已经提出的那样,冗余界面是实现此目的的一种简单方法。似乎一个干净的例子可能会帮助未来的访客。
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);
不隶属于 StackOverflow