这是情景:
我正在使用第三方SDK dll,我应该将PREDEFINED
字符串参数传递给几乎所有的dll方法,并且存在超过800个预定义的可能字符串传递给该方法,文档很差并且示例已过时,有问题的dll是MediaInfoLib
,字符串区分大小写,因此存在一个简单的错误可能发生的风险(任何人都能记住所有这800个字符串的语法......)所以我想要将所有可能的值放在Enumeration中来调用这样的方法:
sub method(byval param as myEnum)
call API method(param.tostring)
End sub
然后这样会发生任何错误,因为我在enum中指定了正确的stringcase语法,并且还有一个优点,我不需要记住800字符串的语法,我可以从中选择所需的值Enum。
嗯,问题是某些字符串的命名如下:
StreamKind/String
CodecID/Url
...我不能把/ char放在Enum中。
当然我认为将“/”字符替换为“_”字符,但我不能这样做,因为存在一些其他字符串名称:
CodecID_Description
Width_Offset
所以,如果我更换这些字符,我会得到误报。
那我该怎么办呢?
我找不到任何可以在Enum中使用的特殊字符,因为它需要与VB运算符一起使用...
我想知道是否存在枚举的接受/禁止字符列表,或者如果有人知道我可以使用的特殊字符而不是“/”字符?,对于特殊字符我是指任何人但不是来自像这样的字母:ÑñÇç,因为我正在搜索一个看起来像分隔符的公认角色。
或任何其他想法?
答案 0 :(得分:3)
我使用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多个。你可能没有的一个问题,但我做的是许多参数是相同的:Codec与音频视频(“编解码器/字符串”)是相同的,它是流参数,使得“编解码器”对于枚举无效名称。因为很多参数是相同的,所以Enum提供了一种很好的方法将它们粘贴到正确的参数上并将其与唯一标识符相关联。
我利用自定义属性来分隔,分类和跟踪每个条目的参数:
如果您定义的属性包含默认返回值,则可以跳过值为默认值的装饰(例如,我的MILvl默认为“标准”),然后您可以在循环中创建List(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提供存储的params的问题:stream to poll是MIGrp,属性键来自MIKey,这可能是你所需要的(我的实现也存储输出,格式化等等)。要在开发时添加新项目,只需添加新的枚举项即可。 (我使用List(of T)以便保留顺序并避免DisplayOrder属性(请参阅下面的链接),您可能希望Dictionary通过Enum值获取各种MediaInfo属性。)
我有3个使用此功能的应用,其中一个是Explorer shell extension。除了将数据发布到ListView以进行显示(MIGrp的另一个用途,以及另一个循环)之外,MediaInfoitem List除了要求之外不需要代码。
HTH
答案 1 :(得分:2)
根据您的方法,您可能需要考虑以下事项(这不适用于评论)。你的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只需要查找“常规”,“音频”和“视频”作为一行中唯一的文本,以了解每个组的开始位置(您的EnamMaker也是目前也包括这些标题作为枚举值)。
或者,您的EnumMaker可以跟踪每个组的结尾并在End Enum
之后添加常量定义:
Public Const Max_MediaInfo_General = 278 '(whatever value)
Public Const Max_MediaInfo_Video = 482
如果enum是一个'库',你实际上使用了应用程序中实际需要的那些子集(其中许多只是因为它在一些模糊的标准中定义为合法标签),那么让EnumMaker添加值(BufferSize = 482
)并使用Const定义,使它们在子集中保持同步。
HTH
答案 2 :(得分:0)
我想分享我的解决方案,此代码将MediaInfo Parametters检索为CSV列表并过滤列表以编写Enum成员及其摘要文档。
要澄清一些事项:
参数进行连接和分类,因此它们不会与mediainfo.dll GetInfoI
方法(需要一个整数)匹配,顺便说一下这个Enum可以与期望String的GetInfo
方法,目的是避免使用GetInfoI
,因为使用此枚举我认为GetInfoI
方法已经过时且无用。
生成的Enum有大约3.000行,需要手动删除一些重复项,大约需要20个重复项,只需要5分钟即可删除它们。
/
字符被__
替换,所以我重写了原始的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
以下是生成枚举的代码:
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获取的原始MediaInfo
vbnet类的完整重写版本(我希望我以正确的方式修改代码,但我不是大师)。
我已经添加了文档,方法重载,枚举以及一些不常用的东西(对我来说)从原始代码中删除,例如非实现方法以及menu
和chapters
成员StreamKind
枚举。