我现在已经完全坚持了大约两天,似乎我无法理解我面临的问题。
目前,我正在编写一个SDP解析库,该库也应该可用于根据其规范(http://tools.ietf.org/html/rfc4566)创建正确的SDP
消息。但规范有时非常开放或不清楚,所以我尝试实现必要的灵活性,同时尽可能接近RFC。
SDP消息可以包含媒体信息(" m
"字段),因为此信息具有以下模式:
m=<media> <port> <proto> <fmt> ...
示例消息可能如下所示:
m=video 49170/2 RTP/AVP 31
查看proto标志,代表媒体传输协议。根据规范,该字段可以具有以下值:
这是一个值列表,因此显然适合采用枚举。
public enum MediaTransportProtocolType {
RTP/AVP
RTP/SAVP
UDP
}
哎呀!但这并不是因为&#34; /&#34;焦炭。那么,我怎么能用它来解析呢?我使用Enumeration
DescriptionAttribute
字段
public enum MediaTransportProtocolType {
[Description("RTP/AVP")
RTP_AVP
[Description("RTP/SAVP")
RTP_SAVP
[Description("UDP")
UDP
}
现在我可以通过它的描述简单地查找适当的媒体传输协议类型。但现在,RFC规范仍在继续:
This memo registers three values [...] If other RTP profiles are
defined in the future [...]
未来的网络设备可能会向我发送一个我不知道的媒体传输协议。由于各种原因System.Enum
不可扩展,因此整个枚举事情不再起作用。
在寻找解决方案的过程中,我遇到了类型安全枚举模式(AKA StringEnum
),如下所述:how can i use switch statement on type-safe enum pattern。这个答案甚至描述了一个让它们可以切换的解决方案,即使它是一个丑陋的解决方案恕我直言。
但同样,这只适用于定义的范围。我使用字典扩展了Type Safe Enumeration
类来存储我可以在解析时查找的实例,但如果我现在不添加新实例,那么我也会添加新的实例。
但是所有其他领域呢?那么铸造呢?
这里的答案描述了一种使用基类并通过显式运算符进行转换的方法:Casting string to type-safe-enum using user-defined conversion
我试了一下,但它并没有像我希望的那样工作。 (无效的强制转换异常,脏的两个强制转换模式,不可扩展)。
如何在提供允许创建正确SDP的库的同时正确轻松地解析SDP信息?
答案 0 :(得分:1)
您可以这样做:
public sealed class MediaTransportProtocolType
{
public static readonly MediaTransportProtocolType RtpAvp =
new MediaTransportProtocolType("RTP/AVP");
public static readonly MediaTransportProtocolType RtpSavp =
new MediaTransportProtocolType("RTP/SAVP");
public static readonly MediaTransportProtocolType Udp =
new MediaTransportProtocolType("UDP");
public static readonly ReadOnlyCollection<MediaTransportProtocolType>
Values = new ReadOnlyCollection<MediaTransportProtocolType>(
new MediaTransportProtocolType[] { RtpAvp, RtpSavp, Udp });
private MediaTransportProtocolType(string name)
{
this.Name = name;
}
public string Name { get; private set; }
public static MediaTransportProtocolType Parse(string value)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException("value");
}
var comparer = StringComparer.OrdinalIgnoreCase;
if (comparer.Equals(value, RtpAvp.Name))
{
return RtpAvp;
}
else if (comparer.Equals(value, RtpSavp.Name))
{
return RtpSavp;
}
else if (comparer.Equals(value, Udp.Name))
{
return Udp;
}
else if (value.StartsWith("RTP/", StringComparison.OrdinalIgnoreCase))
{
// Normally we would throw an exception here, but future
// protocols are expected and we must be forward compatible.
return new MediaTransportProtocolType(name);
}
throw new FormatException(
"The value is not in an expected format. Value: " + value);
}
}
这允许你将它用作这样的枚举:
var type = MediaTransportProtocolType.Udp;
你可以解析它:
var type = MediaTransportProtocolType.Parse(value);
迭代所有已知值:
foreach (var type in MediaTransportProtocolType.Values)
{
}
并且解析返回未知/未来协议类型,只要它们以“RTP /”开头(由规范定义)。
当然问题是,您的图书馆可以处理“未知”协议。如果你不能,你不应该允许解析它们。您应该抛出NotSupportedException
并在添加新协议时更新库。或者,如果您希望其他人扩展,您应该允许其他人定义处理特定协议的实现。