可以在枚举中使用的可接受的特殊字符



这是一个场景:

我使用的是第三方SDK dll,我应该向几乎所有的dll方法传递一个PREDEFINED字符串参数,并且存在800多个预定义的可能字符串可以传递给该方法,文档非常差,示例已经过时,有问题的dll是MediaInfoLib,字符串是区分大小写的,因此很容易发生错误(任何人都可以记住这800个字符串的语法…),所以我想把所有可能的值放在枚举中,以调用这样的方法:

sub method(byval param as myEnum)
  call API method(param.tostring)
End sub

这样,任何错误都可能发生,因为正确的字符串库语法是我在枚举中指定的,而且还有一个优点,那就是我不需要记住800个字符串的语法,我可以从枚举中选择所需的值。

问题是有些字符串是这样命名的:

StreamKind/String
CodecID/Url  

我无法将/char放在枚举中。

当然,我想过用"_"字符替换"/"字符,但我不能这样做,因为存在其他一些字符串名称:

CodecID_Description
Width_Offset

所以如果我替换这些字符,我会得到一个假阳性。

那我该怎么办?

我找不到任何可以在枚举中使用的特殊字符,因为它与VB运算符冲突。。。

我想知道是否存在枚举的接受/禁止字符列表,或者是否有人知道我可以使用的一个好的特殊字符,而不是"/"字符?,对于特殊字符,我指的是任何人,但不是像这样的字母表:ññÇç,因为我正在搜索一个看起来像分隔符的可接受字符。

或者其他想法?

我使用MediaInfo.DLL(很多),知道你在说什么。首先,您可以捕获所有参数以及它们通过其中一个Info方法返回的内容,并将其保存到文本文件中,例如:

Info_Parameters           (this is the mediaInfo key to use to tell it 
                          to dump all the params it knows)
General 
Count                     : Number of objects available in this stream
Status       : bit field (0=IsAccepted, 1=IsFilled, 2=IsUpdated,   3=IsFinished)
StreamCount               : Number of streams of this kind available
StreamKind                : Stream type name

显而易见的答案是,您正试图将Enum几乎用作类:这不仅仅是代码中的一个有意义的标识符,您还希望在其他地方将名称用作参数。去过那里,做了那件事。我是这样处理的(这不会完全回答你的问题,因为你已经有了答案):

Friend Enum MediaInfoItem As Integer
    <Description("File name"), MIKey("FileName"), MIGrp(MediaInfoGroup.File), MIDtl(True)> FileName
    <Description("File Size"), MIKey("FileSize"), MIGrp(MediaInfoGroup.File), MIDtl(True), MIFmt(True)> FileSize
    <Description("Duration"), MIKey("Duration"), MIGrp(MediaInfoGroup.File), MIDtl(True), MIFmt(True)> Duration
    <Description("Format Profile"), MIKey("Format_Profile"), MIGrp(MediaInfoGroup.File), MILvl(PropLvl.XTD)> FormatProfile
    ' mp3 type stuff are in the general, not audio stream
    <Description("Album"), MIKey("Album"), MIGrp(MediaInfoGroup.File), MILvl(PropLvl.DLG)> Album
    <Description("Artist"), MIKey("Artist"), MIGrp(MediaInfoGroup.File), MILvl(PropLvl.DLG)> Artist
    '...
    <Description("Audio Format"), MIKey("Format"), MIGrp(MediaInfoGroup.Audio), MIDtl(True)> AudioFormat
    <Description("Format Info"), MIKey("Format/Info"), MIGrp(MediaInfoGroup.Audio)> AudioFormatInfo
    <Description("Format Profile"), MIKey("Format_Profile"), MIGrp(MediaInfoGroup.Audio), MILvl(PropLvl.XTD)> AudioFormatProfile
    <Description("Codec"), MIKey("Codec/String"), MIGrp(MediaInfoGroup.Audio), MIDtl(True)> AudioCodec
    <Description("Video Format"), MIKey("Format"), MIGrp(MediaInfoGroup.Video), MIDtl(True)> VideoFormat
    <Description("Video Format Info"), MIKey("Format/Info"), MIGrp(MediaInfoGroup.Video)> VideoFormatInfo
    <Description("Format Profile"), MIKey("Format_Profile"), MIGrp(MediaInfoGroup.Video), MILvl(PropLvl.XTD)> VideoFormatProfile
    <Description("Codec"), MIKey("Codec/String"), MIGrp(MediaInfoGroup.Video)> VideoCodec
    ...

我在这里面用了50多个。您可能没有,但我有一个问题,那就是许多参数都是相同的:编解码器对于音频和视频是相同的("编解码器/字符串"),并且是流参数的变化使"编解码器"对于枚举名称无效。因为有这么多参数是相同的,Enum提供了一种很好的方法,可以将它们粘贴到正确的参数上,并将其与一个唯一的标识符相关联。

我使用自定义属性来分离、分类和跟踪每个条目的参数:

  • Description是要在output/UI中使用的文本(我认为这与其中一个注释链接的DisplayName属性没有太大区别,至少就获取而言,但我会研究一下。)
  • MIKey是用于获取此信息的MediaInfo.DLL密钥
  • MIGrop告诉在MediaInfo中轮询哪个流(文件、音频、视频),并控制在ListView中显示时使用哪个组(我还有一个"虚拟"组,我不会进入)
  • MIDtl和MILvl是使用此功能的应用程序的指示器
  • MIFmt确定MediaInfo的返回是否需要格式化才能有用

如果您定义的属性包含一个默认的返回值,您可以跳过值为默认值的装饰(例如,我的MILvl默认为"Standard"),然后您可以在循环中创建一个列表(MediaInfoItem):

Private Sub BuildPropList()
    Dim vals As MediaInfoItem() = [Enum].GetValues(GetType(MediaInfoItem))
    Dim mi As MIProp
    For Each n As MediaInfoItem In vals
        mi = New MIProp(n)       ' magic happens here
        _props.Add(mi)
    Next
End Sub

轮询MediaInfo以获取信息只需浏览propsList并将存储的参数提供给MediaInfo即可:要轮询的流是MIGrp,属性密钥来自MIKey,这可能就是您所需要的(我的实现还存储输出、格式化输出等)。要在开发过程中添加新项,只需添加一个新的Enum项即可。(我使用List(of T),以便保留顺序,并避免DisplayOrder属性(请参阅下面的链接),您可能希望Dictionary通过Enum值获取各种MediaInfo属性。)

我有3个应用程序使用这个,其中一个是Explorer外壳扩展。除了MediaInfoitem List之外,不需要任何代码,只需要将数据发布到ListView中进行显示(MIGrp的另一个用途,只是另一个循环)。

HTH

鉴于您的方法,您可能需要考虑以下内容(这不适合发表评论)。您的Enum Maker对params进行排序,听起来您计划使用Enum名称作为对MediaInfo的param请求(文章中的第1项)。如果添加伪造的MaxGeneral、MaxAudio和MaxVideo条目,您可以很容易地确定要使用哪个streamKind参数。

MediaInfoParms
   Filename
   fileSize
   '...
   EPG_Positions_End    ' i think this is the last General one
   MAX_GENERAL = EPG_Positions_End    
  ' long list of Video enums
  BufferSize              ' last Video I think
  MAX_VIDEO = BufferSize
  ....

现在,当你去呼叫MediaInfo:

 Select Case thisEnumVal 
     Case Is =< MediaInfoParms.MAX_GENERAL
        streamKind = MediaInfo.streamGeneral
     Case Is =< MediaInfoParms.MAX_AUDIO
         streamKind = MediaInfo.streamAudio
     '...

Info_Parameters已经将它们分组,您的EnumMaker只需要查找"常规"、"音频"one_answers"视频"作为一行中的唯一文本,就可以知道每个组的起始位置(您的EnamMaker目前也将这些标题作为枚举值包含在内)。

或者,您的EnumMaker可以只跟踪每个组的末尾,并在End Enum:之后添加常量定义

 Public Const Max_MediaInfo_General = 278  '(whatever value)
 Public Const Max_MediaInfo_Video = 482

如果枚举是一个"库",而你实际上使用了应用程序中实际需要的子集(其中许多只是因为它在某个模糊的标准中被定义为合法标记而存在),那么让EnumMaker添加值(BufferSize = 482)并使用Const定义,以便它们在子集中保持同步。

HTH

我想分享我的解决方案,这段代码以CSV列表的形式检索MediaInfo参数,并过滤该列表以编写Enum成员及其摘要文档。

需要澄清的一些事项:

  1. 参数表是连接和排序的,因此它们与mediainfo.dll GetInfoI方法(需要Integer)不匹配,顺便说一句,这个Enum可以与需要String的GetInfo方法完美地使用,目的是避免使用GetInfoI,因为有了这个Enum,我认为GetInfoI方法已经过时,没有使用完。

  2. 生成的Enum大约有3.000行,它需要手动删除一些重复项,大约20个重复项,只需要5分钟即可删除。

  3. /字符被__替换,所以我重写了原始的MediaInfo VBNET SDK示例,这就是我的方法的样子:

    ''' <summary>
    ''' Gets a piece of information about a file.
    ''' </summary>
    ''' <param name="StreamKind">
    ''' Kind of stream (general, video, audio...).
    ''' </param>
    ''' <param name="StreamNumber">
    ''' Stream number in this kind of stream (first, second...).
    ''' </param>
    ''' <param name="Info">
    ''' The information to retrieve.
    ''' </param>
    ''' <param name="KindOfInfo">
    ''' Kind of information you want about the parameter (the text, the measure, the help...). 
    ''' </param>
    ''' <param name="KindOfSearch">
    ''' Where to look for the parameter . 
    ''' </param>
    Public Function GetInfo(ByVal StreamKind As StreamKind,
                            ByVal StreamNumber As Integer,
                            ByVal Info As MediaInfoOption,
                            Optional ByVal KindOfInfo As InfoKind = InfoKind.Text,
                            Optional ByVal KindOfSearch As InfoKind = InfoKind.Name) As String
    Return System.Runtime.InteropServices.
           Marshal.PtrToStringUni(SafeNativeMethods.
                                  MediaInfo_Get(Handle,
                                                New IntPtr(StreamKind),
                                                New IntPtr(StreamNumber),
                                                Info.ToString.Replace("_s_", "(s)").Replace("__", "/"),
                                                New IntPtr(KindOfInfo),
                                                New IntPtr(KindOfSearch)))
    End Function
    

以下是生成Enum:的代码

Private Sub MakeMediaInfoEnum() Handles MyBase.Shown
    Dim TempFile As String = IO.Path.GetTempFileName
    Dim OutFile As String = "C:MediaInfo Enum.vb"
    Dim ReplaceChar1 As String = "__" ' Replacement for "/" char.
    Dim ReplaceChar2 As String = "_s_" ' Replacement for "(s)" chars.
    Dim sb As New System.Text.StringBuilder
    IO.File.WriteAllText(TempFile,
                         New MediaInfo().LibraryInfo(MediaInfo.MediaInfoLibInfo.Info_Parameters_CSV),
                         System.Text.Encoding.Default)
    sb.AppendLine("Public Enum MediaInfoOption")
    sb.AppendLine("")
    For Each line As String In IO.File.ReadLines(TempFile,
                                                 System.Text.Encoding.Default).
                                                 Where(Function(l) _
                                                       l.Contains(";") _
                                                       AndAlso Not l.ToLower.Contains("deprecated") _
                                                       AndAlso Not l.ToLower.StartsWith("default") _
                                                       AndAlso Not l.ToLower.StartsWith("forced") _
                                                       AndAlso Not l.ToLower.StartsWith("bits-(iixel*frame)")).
                                                 OrderBy(Function(l) l).
                                                 Distinct()
        sb.AppendLine("''' <summary>")
        sb.AppendLine("''' " & If(Not String.IsNullOrEmpty(line.Substring(line.IndexOf(";") + 1)),
                                  line.Substring(line.IndexOf(";") + 1),
                              "( UNDOCUMENTED PARAMETER )"))
        sb.AppendLine("''' </summary>")
        sb.AppendLine(line.Substring(0, line.IndexOf(";")).
                      Replace("/", ReplaceChar1).
                      Replace("(s)", ReplaceChar2))
        sb.AppendLine("")
    Next
    sb.AppendLine("End Enum")
    IO.File.WriteAllText(OutFile, sb.ToString, System.Text.Encoding.Default)
End Sub

上面的代码生成一个文本文件,如下所示:

Public Enum MediaInfoOption
    ''' <summary>
    ''' Format used
    ''' </summary>
    Format
    ''' <summary>
    ''' Commercial name used by vendor for theses setings or Format field if there is no difference
    ''' </summary>
    Format_Commercial
    ''' <summary>
    ''' Commercial name used by vendor for theses setings if there is one
    ''' </summary>
    Format_Commercial_IfAny
    ''' <summary>
    ''' Compression method used
    ''' </summary>
    Format_Compression
    ''' <summary>
    ''' Profile of this Format
    ''' </summary>
    Format_Profile
    ''' <summary>
    ''' Settings needed for decoder used
    ''' </summary>
    Format_Settings
  etc...
End Enum

这是我从SDK中获得的原始MediaInfovbnet类的完整重写版本(我希望我以正确的方式修改了代码,但我不是大师)。

我添加了文档、方法重载、枚举,并且(对我来说)从原始代码中删除了一些不有用的东西,比如未实现的方法以及StreamKind枚举的menuchapters成员。

http://pastebin.com/XGUwW8hQ

最新更新