I need some kind of structure to add, remove and read (get) some values for some settings.
In PHP I would create sth. like:
["root"]["Audio"]["DuplexMode"] = full;
["root"]["AudioSource"]["A0"]["AudioEncoding"] = g711;
["root"]["Network"]["Interface"]["I0"]["Active"]["MACAddress"] = 00:40:8C:9A:1F:56;
and access it like this:
DuplexMode = ["root"]["Audio"]["DuplexMode"];
AudioEncoding = ["root"]["AudioSource"]["A0"]["AudioEncoding"];
MACAddress = ["root"]["Network"]["Interface"]["I0"]["Active"]["MACAddress"];
...
or
foreach (x in ["root"]["AudioSource"]["A0"]) {...}
should give me all the settings under root.AudioSource.A0.
But this seams not to be possible in C#. (Or at least I don't know how...)
Here is the list of settings which is a quite long string I get from a network-camera. (There are not always the same settings for each device.)
root.Audio.DuplexMode=full
root.Audio.MaxListeners=20
root.Audio.ReceiverBuffer=120
root.Audio.ReceiverTimeout=1000
root.Audio.NbrOfConfigs=1
root.Audio.DSCP=0
root.Audio.A0.Enabled=yes
root.Audio.A0.HTTPMessageType=singlepart
root.Audio.A0.Name=
root.Audio.A0.Source=0
root.Audio.A0.AlarmLevel=50
root.Audio.A0.AlarmResolution=50
root.Audio.A0.AlarmLowLimit=10
root.Audio.A0.AlarmHighLimit=6500
root.AudioSource.NbrOfSources=1
root.AudioSource.A0.Name=Audio
root.AudioSource.A0.AudioEncoding=g711
root.AudioSource.A0.InputType=mic
root.AudioSource.A0.InputGain=auto
root.AudioSource.A0.OutputGain=0
root.AudioSource.A0.SampleRate=8000
root.AudioSource.A0.HWSampleRate=16000
root.AudioSource.A0.BitRate=64000
root.AudioSource.A0.CustomReg=
root.AudioSource.A0.AudioSupport=yes
root.Bandwidth.Limit=0
root.Brand.Brand=AXIS
root.Brand.ProdFullName=AXIS M1031-W Network Camera
root.Brand.ProdShortName=AXIS M1031-W
root.Brand.ProdNbr=M1031-W
root.Brand.ProdType=Network Camera
root.Brand.WebURL=http://www.axis.com/
root.Event.E0.Name=NightLight
root.Event.E0.Type=T
root.Event.E0.Enabled=yes
root.Event.E0.Priority=1
root.Event.E0.Image=0
root.Event.E0.HWInputs=1
root.Event.E0.SWInput=
root.Event.E0.Weekdays=1111111
root.Event.E0.Starttime=19:00
root.Event.E0.Duration=12:00
root.Event.E0.MinimumTriggerInterval=00:00:00
root.Event.E0.MinimumTriggerTimePeriod=00:00:00
root.Event.E0.ImageURLSettingsEnabled=no
root.Event.E0.ImageURLSettings=
root.Event.E0.IncludePreTrigger=no
root.Event.E0.PreTriggerDuration=
root.Event.E0.PreTriggerDurationUnit=s
root.Event.E0.IncludePostTrigger=no
root.Event.E0.PostTriggerDuration=
root.Event.E0.PostTriggerDurationUnit=s
root.Event.E0.IncludeBestEffort=no
root.Event.E0.BestEffortDuration=0
root.Event.E0.BestEffortDurationUnit=s
root.Event.E0.IncludeAudio=no
root.Event.E0.MPEGPreTriggerDuration=5
root.Event.E0.MPEGPostTriggerDuration=2
root.Event.E0.VideoFormat=
root.Event.E0.FrameRate=
root.Event.E0.Actions.A0.Type=N
root.Event.E0.Actions.A0.Protocol=Light
root.Event.E0.Actions.A0.Order=0
root.Event.E0.Actions.A0.Light=1
root.Event.E0.Actions.A0.Activate=100
root.Event.E0.Actions.A0.Inactivate=-0
root.Event.E0.Actions.A0.Duration=30
root.Event.E0.Actions.A0.Unit=s
root.HTTPS.Certificate=none
root.HTTPS.Enabled=no
root.HTTPS.Port=443
root.Image.TriggerDataEnabled=yes
root.Image.ReferrersEnabled=no
root.Image.Referrers=
root.Image.MaxViewers=20
root.Image.MotionDetection=yes
root.Image.NbrOfConfigs=1
root.Image.RFCCompliantMultipartEnabled=yes
root.Image.PrivacyMaskType=mask_windows
root.Image.OverlayPath=/etc/overlays/axis(128x44).ovl
root.Image.DateFormat=YYYY-MM-DD
root.Image.OwnDateFormat=%F
root.Image.OwnDateFormatEnabled=no
root.Image.TimeFormat=24
root.Image.OwnTimeFormat=%T
root.Image.OwnTimeFormatEnabled=no
root.Image.TimeResolution=1
root.Image.I0.Name=
root.Image.I0.Source=0
root.Image.I0.Appearance.Resolution=640x480
root.Image.I0.Appearance.Compression=30
root.Image.I0.Appearance.Rotation=0
root.Image.I0.Appearance.MirrorEnabled=no
root.Image.I0.Appearance.ColorEnabled=yes
root.Image.I0.MPEG.ConfigHeaderInterval=1
root.Image.I0.MPEG.UserDataEnabled=yes
root.Image.I0.MPEG.UserDataInterval=1
root.Image.I0.MPEG.ICount=1
root.Image.I0.MPEG.PCount=14
root.Image.I0.MPEG.Complexity=50
root.Image.I0.MPEG.ResyncMarkerEnabled=yes
root.Image.I0.MPEG.H264.PSEnabled=no
root.Image.I0.Overlay.Enabled=no
root.Image.I0.Overlay.XPos=0
root.Image.I0.Overlay.YPos=0
root.Image.I0.Overlay.MaskWindows.Color=black
root.Image.I0.Overlay.MaskWindows.M0.Enabled=no
root.Image.I0.Overlay.MaskWindows.M0.XPos=303
root.Image.I0.Overlay.MaskWindows.M0.YPos=2
root.Image.I0.Overlay.MaskWindows.M0.Width=160
root.Image.I0.Overlay.MaskWindows.M0.Height=48
root.Image.I0.Overlay.MaskWindows.M0.Name=Mask%200
root.Image.I0.Overlay.MaskWindows.M1.Enabled=no
root.Image.I0.Overlay.MaskWindows.M1.XPos=124
root.Image.I0.Overlay.MaskWindows.M1.YPos=4
root.Image.I0.Overlay.MaskWindows.M1.Width=148
root.Image.I0.Overlay.MaskWindows.M1.Height=56
root.Image.I0.Overlay.MaskWindows.M1.Name=Mask%201
root.Image.I0.Overlay.MaskWindows.M2.Enabled=no
root.Image.I0.Overlay.MaskWindows.M2.XPos=583
root.Image.I0.Overlay.MaskWindows.M2.YPos=52
root.Image.I0.Overlay.MaskWindows.M2.Width=54
root.Image.I0.Overlay.MaskWindows.M2.Height=113
root.Image.I0.Overlay.MaskWindows.M2.Name=Mask%202
root.Image.I0.RateControl.Mode=vbr
root.Image.I0.RateControl.Priority=framerate
root.Image.I0.RateControl.TargetBitrate=0
root.Image.I0.RateControl.MaxFPS=30
root.Image.I0.RateControl.MinFPS=1
root.Image.I0.RateControl.MaxCompression=100
root.Image.I0.RateControl.MinCompression=0
root.Image.I0.RateControl.MaxBitrate=0
root.Image.I0.SizeControl.MaxFrameSize=0
root.Image.I0.SizeControl.DiffFrameSize=0
root.Image.I0.Stream.Duration=0
root.Image.I0.Stream.NbrOfFrames=0
root.Image.I0.Stream.FPS=15
root.Image.I0.Text.DateEnabled=no
root.Image.I0.Text.ClockEnabled=no
root.Image.I0.Text.TextEnabled=no
root.Image.I0.Text.String=ET1
root.Image.I0.Text.Position=top
root.Image.I0.TriggerData.IOEnabled=yes
root.Image.I0.TriggerData.AudioEnabled=yes
root.Image.I0.TriggerData.TamperingEnabled=yes
root.Image.I0.TriggerData.MotionDetectionEnabled=yes
root.Image.I0.TriggerData.MotionLevelEnabled=no
root.Image.I0.TriggerData.UserTriggers=
root.ImageSource.NbrOfSources=1
root.ImageSource.MotionDetection=no
root.ImageSource.I0.Name=Camera
root.ImageSource.I0.Sensor.WhiteBalance=auto
root.ImageSource.I0.Sensor.Exposure=flickerfree50
root.ImageSource.I0.Sensor.MaxExposureTime=10000
root.ImageSource.I0.Sensor.MinExposureTime=10000
root.ImageSource.I0.Sensor.MaxGain=100
root.ImageSource.I0.Sensor.MinGain=0
root.ImageSource.I0.Sensor.ExposureValue=59
root.ImageSource.I0.Sensor.ExposurePriority=50
root.ImageSource.I0.Sensor.ColorDesaturation=100
root.ImageSource.I0.Sensor.Brightness=51
root.ImageSource.I0.Sensor.Contrast=56
root.ImageSource.I0.Sensor.ColorLevel=60
root.ImageSource.I0.Sensor.Sharpness=64
root.ImageSource.I0.Sensor.BacklightCompensation=yes
root.ImageSource.I0.Sensor.DynamicPixelCorrection=yes
root.ImageSource.I0.Sensor.AspectRatio=
root.ImageSource.I0.Sensor.ExposureWindow=auto
root.ImageSource.I0.Sensor.CustomExposureWindow.Weight=100
root.Input.NbrOfInputs=1
root.IOPort.I0.Configurable=no
root.IOPort.I0.Direction=input
root.IOPort.I0.Input.Name=PIR sensor
root.IOPort.I0.Input.Trig=closed
root.Layout.DefaultVideoFormat=mjpeg
root.Layout.ShowVideoFormatDropDown=yes
root.Layout.DefaultStreamProfile=
root.Layout.ViewerIE=activex
root.Layout.ViewerOther=spush
root.Layout.SetupLinkEnabled=yes
root.Layout.SnapshotEnabled=no
root.Layout.PlainConfigEnabled=no
root.Layout.ShowAMCToolbar=yes
root.Layout.AMCRecordMedia=1
root.Layout.Axis=yes
root.Layout.OwnHomePageEnabled=no
root.Layout.OwnHomePagePath=dummy
root.Layout.MPEGInstallationEnabled=yes
root.Layout.H264InstallationEnabled=yes
root.Layout.AACInstallationEnabled=yes
root.Layout.EnableBasicSetup=yes
root.Layout.InstantReplayEnabled=no
root.Layout.InstantReplayTimeOffset=30
root.Layout.PlayAudioClipEnabled=yes
root.Layout.CustomLink.C0.Enabled=no
root.Layout.CustomLink.C0.Name=Custom link 1
root.Layout.CustomLink.C0.URL=http://
root.Layout.CustomLink.C0.Usage=cgi
root.Layout.CustomLink.C1.Enabled=no
root.Layout.CustomLink.C1.Name=Custom link 2
root.Layout.CustomLink.C1.URL=http://
root.Layout.CustomLink.C1.Usage=cgi
root.Layout.CustomLink.C2.Enabled=no
root.Layout.CustomLink.C2.Name=Custom link 3
root.Layout.CustomLink.C2.URL=http://
root.Layout.CustomLink.C2.Usage=cgi
root.Layout.CustomLink.C3.Enabled=no
root.Layout.CustomLink.C3.Name=Custom link 4
root.Layout.CustomLink.C3.URL=http://
root.Layout.CustomLink.C3.Usage=cgi
root.Layout.Trigger.T0.Enabled=no
root.LightControl.L0.Name=Light
root.LightControl.L0.DriverType=pwm
root.LightControl.L0.SourceType=whiteled
root.LightControl.L0.Driver=pa18
root.LightControl.L0.Button=actinact
root.LightControl.L0.Activate=-100
root.LightControl.L0.Inactivate=-0
root.LightControl.L0.PulseTime=0
root.Log.Access.MaxSize=40000
root.Log.Access.Critical=detailed
root.Log.Access.Warning=detailed
root.Log.Access.Informational=off
root.Log.System.MaxSize=40000
root.Log.System.Critical=on
root.Log.System.Warning=on
root.Log.System.Informational=on
root.MailLogd.ToEmail=
root.MailLogd.LogSendLevel=0
root.MediaClip.MaxGroups=10
root.MediaClip.M0.Name=Burglar_Alarm_Short
root.MediaClip.M0.Location=/etc/audioclips/Burglar_Alarm_Short_8bit_32kHz_mono_PCM-16bit-little.wav
root.MediaClip.M0.Type=audio
root.MediaClip.M6.Name=Camera clicks
root.MediaClip.M6.Location=/etc/audioclips/camera_clicks16k.au
root.MediaClip.M6.Type=audio
root.MediaClip.M7.Name=Pssst, Psst!
root.MediaClip.M7.Location=/etc/audioclips/pssst_psst16k.au
root.MediaClip.M7.Type=audio
root.MediaClip.M8.Name=Intruder
root.MediaClip.M8.Location=/etc/audioclips/intruder16k.au
root.MediaClip.M8.Type=audio
root.MediaClip.M9.Name=Dog barking
root.MediaClip.M9.Location=/etc/audioclips/dog_barking16k.au
root.MediaClip.M9.Type=audio
root.Motion.M0.Name=DefaultWindow
root.Motion.M0.ImageSource=0
root.Motion.M0.Left=0
root.Motion.M0.Right=9999
root.Motion.M0.Top=86
root.Motion.M0.Bottom=9998
root.Motion.M0.WindowType=include
root.Motion.M0.Sensitivity=95
root.Motion.M0.History=93
root.Motion.M0.ObjectSize=3
root.Network.Media=auto
root.Network.Autoneg=normal
root.Network.InterfaceSelectMode=auto
root.Network.HostName=axis-00408c9a1f56
root.Network.DNSServer1=192.168.69.251
root.Network.DNSServer2=0.0.0.0
root.Network.tcpECN=1
root.Network.Enabled=yes
root.Network.BootProto=none
root.Network.IPAddress=192.168.68.127
root.Network.SubnetMask=255.255.254.0
root.Network.Broadcast=192.168.69.255
root.Network.DefaultRouter=192.168.69.254
root.Network.DomainName=
root.Network.ARPPingIPAddress.Enabled=yes
root.Network.AxisNS.Enabled=yes
root.Network.AxisNS.LockButton=no
root.Network.AxisNS.UpdatePeriod=1
root.Network.AxisNS.CheckPeriod=10
root.Network.AxisNS.ServerList=www0.axiscam.net,www1.axiscam.net,195.60.68.29,195.60.68.30
root.Network.AxisNS.ServerPath=reg_cam.php
root.Network.AxisNS.ServerLink=www.axiscam.net
root.Network.AxisNS.CheckIPAddress=0.0.0.0
root.Network.AxisNS.CheckTTL=0
root.Network.Bonjour.Enabled=yes
root.Network.Bonjour.FriendlyName=AXIS M1031-W - 00408C9A1F56
root.Network.DHCP.StoreIPAddresseth0=no
root.Network.DHCP.StoreIPAddresseth1=no
root.Network.DHCP.IPCheckEnabled=yes
root.Network.DHCP.VendorClass=AXIS,Network Camera,M1031-W,5.20.1
root.Network.DHCP.Fqdn=
root.Network.DHCP.Timeout=0
root.Network.DHCP.Retries=20
root.Network.DNSUpdate.Enabled=no
root.Network.DNSUpdate.DNSName=Securitec
root.Network.DNSUpdate.TTL=30
root.Network.eth0.MACAddress=00:40:8C:9A:1F:56
root.Network.eth0.IPAddress=192.168.68.127
root.Network.eth0.SubnetMask=255.255.254.0
root.Network.eth0.Broadcast=192.168.69.255
root.Network.eth0.IPv6.IPAddresses=fe80::240:8cff:fe9a:1f56/64
root.Network.Filter.Enabled=no
root.Network.Filter.Input.Policy=allow
root.Network.Filter.Input.AcceptAddresses=
root.Network.Filter.Log.Enabled=yes
root.Network.FTP.Enabled=yes
root.Network.HTTP.AuthenticationPolicy=basic_digest
root.Network.HTTP.AuthenticationPolicySet=yes
root.Network.HTTP.AuthenticationWithQop=no
root.Network.Interface.I0.SystemDevice=eth0
root.Network.Interface.I0.Type=802.3
root.Network.Interface.I0.Active.MACAddress=00:40:8C:9A:1F:56
root.Network.Interface.I0.Active.Active=no
root.Network.Interface.I0.Active.IPAddress=
root.Network.Interface.I0.Active.SubnetMask=
root.Network.Interface.I0.Active.Broadcast=
root.Network.Interface.I0.Active.IPv6Addresses=
root.Network.Interface.I0.dot1x.Enabled=no
root.Network.Interface.I0.dot1x.EAPOLVersion=1
root.Network.Interface.I0.dot1x.Status=Stopped
root.Network.Interface.I0.dot1x.EAPTLS.Identity=xxx
root.Network.Interface.I0.dot1x.EAPTLS.PrivateKeyPassword=*****
root.Network.Interface.I0.Link.MTU=1500
root.Network.Interface.I0.Link.BootProto=none
root.Network.Interface.I0.Link.Media=auto
root.Network.Interface.I0.Link.Autoneg=normal
root.Network.Interface.I0.Link.IPv4Enabled=yes
root.Network.Interface.I0.Link.IPv6Enabled=no
root.Network.Interface.I0.Link.AcceptRA=yes
root.Network.Interface.I0.Link.DHCPv6=auto
root.Network.Interface.I0.Manual.IPAddress=192.168.68.127
root.Network.Interface.I0.Manual.SubnetMask=255.255.254.0
root.Network.Interface.I0.Manual.Broadcast=192.168.69.255
root.Network.Interface.I0.Manual.DefaultRouter=192.168.69.254
root.Network.Interface.I0.Manual.IPv6Address=
root.Network.Interface.I0.Manual.IPv6DefaultRouter=
root.Network.Interface.I0.ZeroConf.Enabled=yes
root.Network.Interface.I0.ZeroConf.IPAddress=
root.Network.Interface.I0.ZeroConf.SubnetMask=
root.Network.Interface.I1.SystemDevice=eth1
root.Network.Interface.I1.Type=802.11
root.Network.Interface.I1.Active.MACAddress=00:40:8C:9A:1F:56
root.Network.Interface.I1.Active.Active=yes
root.Network.Interface.I1.Active.IPAddress=192.168.68.127
root.Network.Interface.I1.Active.SubnetMask=255.255.254.0
root.Network.Interface.I1.Active.Broadcast=192.168.69.255
root.Network.Interface.I1.Active.IPv6Addresses=fe80::240:8cff:fe9a:1f56/64
root.Network.Interface.I1.dot1x.EAPOLVersion=1
root.Network.Interface.I1.dot1x.EAPTLS.Identity=
root.Network.Interface.I1.dot1x.EAPTLS.PrivateKeyPassword=*****
root.Network.Interface.I1.Link.MTU=1500
root.Network.Interface.I1.Link.BootProto=none
root.Network.Interface.I1.Link.IPv4Enabled=yes
root.Network.Interface.I1.Link.IPv6Enabled=no
root.Network.Interface.I1.Link.AcceptRA=yes
root.Network.Interface.I1.Link.DHCPv6=auto
root.Network.Interface.I1.Manual.IPAddress=192.168.68.127
root.Network.Interface.I1.Manual.SubnetMask=255.255.254.0
root.Network.Interface.I1.Manual.Broadcast=192.168.69.255
root.Network.Interface.I1.Manual.DefaultRouter=192.168.69.254
root.Network.Interface.I1.Manual.IPv6Address=
root.Network.Interface.I1.Manual.IPv6DefaultRouter=
root.Network.Interface.I1.ZeroConf.Enabled=yes
root.Network.Interface.I1.ZeroConf.IPAddress=169.254.248.199
root.Network.Interface.I1.ZeroConf.SubnetMask=255.255.0.0
root.Network.IPv6.Enabled=no
root.Network.IPv6.AcceptRA=yes
root.Network.IPv6.DHCPv6=auto
root.Network.IPv6.IPAddress=
root.Network.IPv6.DefaultRouter=
root.Network.QoS.Class1.Desc=AxisLiveVideo
root.Network.QoS.Class1.DSCP=0
root.Network.QoS.Class2.Desc=AxisLiveAudio
root.Network.QoS.Class2.DSCP=0
root.Network.QoS.Class3.Desc=AxisEventAlarm
root.Network.QoS.Class3.DSCP=0
root.Network.QoS.Class4.Desc=AxisManagement
root.Network.QoS.Class4.DSCP=0
root.Network.Resolver.NameServerList=192.168.69.251
root.Network.Resolver.ObtainFromDHCP=no
root.Network.Resolver.Search=
root.Network.Resolver.NameServer1=192.168.69.251
root.Network.Resolver.NameServer2=
root.Network.Routing.DefaultRouter=192.168.69.254
root.Network.Routing.IPv6.DefaultRouter=
root.Network.RTP.NbrOfRTPGroups=1
root.Network.RTP.StartPort=50000
root.Network.RTP.EndPort=50999
root.Network.RTP.VideoDSCP=0
root.Network.RTP.AudioDSCP=0
root.Network.RTP.R0.VideoAddress=239.226.31.86
root.Network.RTP.R0.VideoPort=0
root.Network.RTP.R0.AudioAddress=239.226.31.214
root.Network.RTP.R0.AudioPort=0
root.Network.RTP.R0.TTL=5
root.Network.RTSP.Enabled=yes
root.Network.RTSP.Port=554
root.Network.RTSP.Timeout=60
root.Network.RTSP.ProtViewer=password
root.Network.RTSP.AllowPathAsURL=yes
root.Network.RTSP.AuthenticateOverHTTP=no
root.Network.RTSP.AllowClientTransportSettings=no
root.Network.UPnP.Enabled=yes
root.Network.UPnP.FriendlyName=AXIS M1031-W - Office WiFi Cam
root.Network.UPnP.NATTraversal.Enabled=no
root.Network.UPnP.NATTraversal.Router=
root.Network.UPnP.NATTraversal.ExternalIPAddress=
root.Network.UPnP.NATTraversal.Active=no
root.Network.UPnP.NATTraversal.MinPort=32768
root.Network.UPnP.NATTraversal.MaxPort=65535
root.Network.VolatileHostName.ObtainFromDHCP=no
root.Network.VolatileHostName.HostName=axis-00408c9a1f56
root.Network.Wireless.ESSID=SecuriTec
root.Network.Wireless.MODE=managed
root.Network.Wireless.W0.Enabled=yes
root.Network.Wireless.W0.Method=WPA-PSK
root.Network.Wireless.W0.GenerationMethod=psk-phrase
root.Network.Wireless.W0.Passphrase=*****
root.Network.Wireless.W0.Key=
root.Network.Wireless.W1.Enabled=no
root.Network.Wireless.W1.Method=WPA-ENTERPRISE
root.Network.Wireless.W1.Dot1XMethod=EAPTLS
root.Network.Wireless.WEP.Enabled=no
root.Network.Wireless.WEP.KeyLength=128
root.Network.Wireless.WEP.GenerationMethod=manual
root.Network.Wireless.WEP.Passphrase=
root.Network.Wireless.WEP.ActiveKey=1
root.Network.Wireless.WEP.Key1=
root.Network.Wireless.WEP.Key2=
root.Network.Wireless.WEP.Key3=
root.Network.Wireless.WEP.Key4=
root.Network.Wireless.WEP.Authentication=open
root.Network.ZeroConf.Enabled=yes
root.Network.ZeroConf.IPAddress=169.254.248.199
root.Network.ZeroConf.SubnetMask=255.255.0.0
root.Notify.AtBoot=no
root.Notify.TextType=simple
root.Notify.TextField=Your text here
root.Notify.KnownIP=192.168.68.127
root.Notify.KnownIPV6=
root.Notify.FTP.Enabled=no
root.Notify.FTP.HostName=
root.Notify.FTP.UserName=
root.Notify.FTP.Password=
root.Notify.FTP.UploadPath=
root.Notify.FTP.PassiveMode=no
root.Notify.FTP.Port=21
root.Notify.HTTP.Enabled=no
root.Notify.HTTP.URL=http://
root.Notify.HTTP.Custom=
root.Notify.HTTP.UserName=
root.Notify.HTTP.Password=
root.Notify.HTTP.Proxy=
root.Notify.HTTP.ProxyPort=
root.Notify.HTTP.ProxyUser=
root.Notify.HTTP.ProxyPass=
root.Notify.SMTP.Enabled=no
root.Notify.SMTP.ToEmail=
root.Notify.SMTP.FromEmail=
root.Notify.SMTP.Subject=
root.Output.NbrOfOutputs=0
root.PIRSensor.Sensitivity=75
root.Properties.API.HTTP.Version=3
root.Properties.API.HTTP.AdminPath=/operator/basic.shtml
root.Properties.API.Metadata.Metadata=yes
root.Properties.API.Metadata.Version=1.0
root.Properties.API.RTSP.Version=2.01
root.Properties.API.RTSP.RTSPAuth=yes
root.Properties.API.WebService.WebService=yes
root.Properties.API.WebService.ONVIF.ONVIF=yes
root.Properties.API.WebService.ONVIF.Version=1.01
root.Properties.Audio.Audio=yes
root.Properties.Audio.Format=g711,g726,aac
root.Properties.Audio.DuplexMode=full,half,post,get
root.Properties.Audio.InputType=mic
root.Properties.Audio.Decoder.Format=g711,g726,axis-mulaw-128
root.Properties.Firmware.BuildNumber=1
root.Properties.Firmware.BuildDate=Jun 23 2016 13:16
root.Properties.Firmware.Version=5.20.4
root.Properties.HTTPS.HTTPS=yes
root.Properties.Image.Rotation=0,180
root.Properties.Image.Resolution=640x480,480x360,320x240,240x180,160x120,176x144
root.Properties.Image.Format=jpeg,mjpeg,mpeg4,h264,bitmap
root.Properties.Image.NbrOfViews=1
root.Properties.LightControl.LightControl=yes
root.Properties.Motion.Motion=yes
root.Properties.Motion.MaxNbrOfWindows=10
root.Properties.RemoteService.RemoteService=yes
root.Properties.RTC.RTC=no
root.Properties.System.Language=English
root.Properties.System.HardwareID=170
root.Properties.System.SerialNumber=00408C9A1F56
root.Properties.System.Architecture=armv5tejl
root.Properties.Tampering.Tampering=yes
root.Properties.TemperatureSensor.TemperatureSensor=yes
root.Properties.TemperatureSensor.TemperatureControl=no
root.Properties.TemperatureSensor.Fan=no
root.Properties.TemperatureSensor.Heater=no
root.RemoteService.Enabled=oneclick
root.RemoteService.Proxy=
root.RemoteService.RemoteServerURL=http://dispatcher.sts.axis.com:80/axissts/axissts.cgi,http://dispatcher.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchse1.sts.axis.com:80/axissts/axissts.cgi,http://dispatchse1.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchse2.sts.axis.com:80/axissts/axissts.cgi,http://dispatchse2.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchus1.sts.axis.com:80/axissts/axissts.cgi,http://dispatchjp1.sts.axis.com:80/axissts/axissts.cgi,http://87.237.210.63:80/axissts/axissts.cgi,http://87.237.210.63:8080/axissts/axissts.cgi,http://85.235.16.249:80/axissts/axissts.cgi,http://85.235.16.249:8080/axissts/axissts.cgi,http://85.235.16.250:80/axissts/axissts.cgi,http://85.235.16.250:8080/axissts/axissts.cgi
root.RemoteService.Timeout=100
root.RemoteService.ConnectTimeout=15
root.RemoteService.BrandSpec=1275677567
root.RemoteService.Reconnect=0
root.RemoteService.TimeMode=NTP
root.SMTP.MailServer1=
root.SMTP.MailServer2=
root.SMTP.MailServerPort1=25
root.SMTP.MailServerPort2=25
root.SMTP.MailServerSSL1=no
root.SMTP.MailServerSSL2=no
root.SMTP.FromEmail=
root.SMTP.Authentication.A1.Enabled=no
root.SMTP.Authentication.A1.UserName=
root.SMTP.Authentication.A1.Password=
root.SMTP.Authentication.A1.WeakestMethod=Login
root.SMTP.Authentication.A1.UsePOP=no
root.SMTP.Authentication.A1.POPServer=
root.SMTP.Authentication.A2.Enabled=no
root.SMTP.Authentication.A2.UserName=
root.SMTP.Authentication.A2.Password=
root.SMTP.Authentication.A2.WeakestMethod=Login
root.SMTP.Authentication.A2.UsePOP=no
root.SMTP.Authentication.A2.POPServer=
root.SMTP.SSL.S1.RootCertificate=
root.SMTP.SSL.S1.ClientCertificate=
root.SMTP.SSL.S1.ClientPrivateKey=
root.SMTP.SSL.S1.ClientPrivateKeyPasswd=
root.SMTP.SSL.S2.RootCertificate=
root.SMTP.SSL.S2.ClientCertificate=
root.SMTP.SSL.S2.ClientPrivateKey=
root.SMTP.SSL.S2.ClientPrivateKeyPasswd=
root.SNMP.Enabled=no
root.SNMP.InitialUserPasswdSet=no
root.SNMP.InitialUserPasswd=*****
root.SNMP.EngineBoots=1
root.SNMP.V1=no
root.SNMP.V2c=no
root.SNMP.V3=no
root.SNMP.V1ReadCommunity=public
root.SNMP.V1WriteCommunity=write
root.SNMP.DSCP=0
root.SNMP.Trap.Enabled=no
root.SNMP.Trap.T0.Address=
root.SNMP.Trap.T0.Community=public
root.SNMP.Trap.T0.AuthFail.Enabled=no
root.SNMP.Trap.T0.ColdStart.Enabled=no
root.SNMP.Trap.T0.LinkUp.Enabled=no
root.SNMP.Trap.T0.WarmStart.Enabled=no
root.SOCKS.Enabled=no
root.SOCKS.Server=socks
root.SOCKS.ServerPort=1080
root.SOCKS.ServerType=4
root.SOCKS.LocalNetworks=10.0.0.0/255.0.0.0, 172.16.0.0/255.240.0.0, 192.168.0.0/255.255.255.0
root.SOCKS.UserName=
root.SOCKS.Password=
root.StatusLED.Usage=on
root.StatusLED.FlashInterval=4
root.StreamCache.Size=12582912
root.StreamCache.MaxGroups=20
root.StreamCache.S0.Enabled=no
root.StreamCache.S0.Options=
root.StreamCache.S0.RequestedLengthTime=30
root.StreamProfile.MaxGroups=20
root.StreamProfile.S0.Name=Quality
root.StreamProfile.S0.Description=Best image quality and full frame rate.
root.StreamProfile.S0.Parameters=videocodec=h264&resolution=640x480&compression=20&fps=0&videokeyframeinterval=8&videobitrate=0
root.StreamProfile.S0.Default.Name=Quality
root.StreamProfile.S0.Default.Description=Best image quality and full frame rate.
root.StreamProfile.S0.Default.Parameters=videocodec=h264&resolution=640x480&compression=20&fps=0&videokeyframeinterval=8&videobitrate=0
root.StreamProfile.S1.Name=Balanced
root.StreamProfile.S1.Description=Medium image quality and frame rate.
root.StreamProfile.S1.Parameters=videocodec=h264&resolution=640x480&compression=30&fps=15&videokeyframeinterval=15&videobitrate=0
root.StreamProfile.S1.Default.Name=Balanced
root.StreamProfile.S1.Default.Description=Medium image quality and frame rate.
root.StreamProfile.S1.Default.Parameters=videocodec=h264&resolution=640x480&compression=30&fps=15&videokeyframeinterval=15&videobitrate=0
root.StreamProfile.S2.Name=Bandwidth
root.StreamProfile.S2.Description=Low bandwidth with medium image quality.
root.StreamProfile.S2.Parameters=resolution=320x240&compression=50&fps=15&videokeyframeinterval=32&videobitrate=250&videobitratepriority=framerate&videocodec=h264
root.StreamProfile.S2.Default.Name=Bandwidth
root.StreamProfile.S2.Default.Description=Low bandwidth with medium image quality.
root.StreamProfile.S2.Default.Parameters=videocodec=h264&resolution=640x480&compression=50&fps=15&videokeyframeinterval=32&videobitrate=250&videomaxbitrate=1000&videobitratepriority=framerate
root.StreamProfile.S3.Name=Mobile
root.StreamProfile.S3.Description=Mobile device settings.
root.StreamProfile.S3.Parameters=videocodec=h264&resolution=176x144&compression=50&fps=15&videokeyframeinterval=32&videobitrate=120&videomaxbitrate=128&videobitratepriority=quality&audio=0
root.StreamProfile.S3.Default.Name=Mobile
root.StreamProfile.S3.Default.Description=Mobile device settings.
root.StreamProfile.S3.Default.Parameters=videocodec=h264&resolution=176x144&compression=50&fps=15&videokeyframeinterval=32&videobitrate=120&videomaxbitrate=128&videobitratepriority=quality&audio=0
root.System.BoaPort=80
root.System.AlternateBoaPort=0
root.System.BoaDSCP=0
root.System.BoaProtViewer=password
root.System.RootPwdSet=yes
root.System.BoaGroupPolicy.admin=http
root.System.BoaGroupPolicy.operator=http
root.System.BoaGroupPolicy.viewer=http
root.Tampering.T0.DarkDetectionEnabled=yes
root.Tampering.T0.MinDuration=20
root.Tampering.T0.DarkThreshold=90
root.Time.ServerTime=10:38:13
root.Time.ServerDate=2016-10-26
root.Time.ObtainFromDHCP=no
root.Time.POSIXTimeZone=CET-1CEST,M3.5.0,M10.5.0/3
root.Time.SyncSource=NTP
root.Time.DST.Enabled=yes
root.Time.NTP.VolatileServer=
root.Time.NTP.Server=192.168.69.251
root.WebService.Enabled=no
root.WebService.UsernameToken.ReplayAttackProtection=yes
root.WebService.UsernameToken.WaitForNTP=no
How yould you do this in C#?
You can use an ExpandoObject with a params indexer to access it, something like this (that's just an example, you'll need to do some testing around it and handle things like single key access etc):
public class AssociativeArray
{
private dynamic _data = new ExpandoObject();
public object this[params string[] keys]
{
get
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
lastObject = dic[key] as ExpandoObject;
}
return (lastObject as IDictionary<string, object>)[keys.Last()];
}
set
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
dic.Add(key, new ExpandoObject());
lastObject = dic[key];
}
(lastObject as IDictionary<string, object>).Add(keys.Last(), value);
}
}
}
you can then use it like this:
var arr = new AssociativeArray();
arr["root", "Audio", "Dup"] = 33;
Console.Write(arr["root", "Audio", "Dup"]);
PS. I'm using the suggestion from this answer to cast the ExpandoObject as a Dictionary
You can use a ExpandoObject for this case. You can cast the ExpandoObject to a Dictionary and add the values:
var text = File.ReadAllText("$settingsfile");
var keyValuePairs = text.Split('\n')
.Select(line => Tuple.Create(line.Split('=')[0].Trim(), line.Split('=')[1].Trim()));
dynamic root = new ExpandoObject();
foreach (var tup in keyValuePairs)
{
var path = tup.Item1.Split('.').Skip(1).ToList();
var setting = path.Last();
var value = tup.Item2;
IDictionary<string, object> resolvedObject = root;
foreach (var component in path.Take(path.Count - 1))
{
if (!resolvedObject.ContainsKey(component))
{
resolvedObject.Add(component, new ExpandoObject());
}
resolvedObject = (IDictionary<string, object>) resolvedObject[component];
}
resolvedObject[setting] = value;
}
Console.WriteLine(">> " + root.System.BoaPort);
Thanks to KMoussa!
Not the most beautiful code, but it works:
public class cAssociativeArray
{
private dynamic _data = new ExpandoObject();
public object this[params string[] keys]
{
get { return getValue(keys); }
set { setValue(value, keys); }
}
private void setValue(object _value, params string[] keys)
{
dynamic lastObject = _data;
string lKey = keys.Last();
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
if (!dic.ContainsKey(key))
{
dic.Add(key, new ExpandoObject());
}
lastObject = dic[key];
}
if ((lastObject as IDictionary<string, object>) != null)
{
if (!(lastObject as IDictionary<string, object>).ContainsKey(keys.Last())) // add value
{
(lastObject as IDictionary<string, object>).Add(lKey, _value);
}
else //change value
{
if (keys.Count() > 1)
{
(lastObject as IDictionary<string, object>)[lKey] = _value;
}
}
}
}
private string getValue(params string[] keys)
{
dynamic lastObject = _data;
string lKey = keys.Last();
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return null;
}
}
if (((lastObject as IDictionary<string, object>) != null) && ((lastObject as IDictionary<string, object>).ContainsKey(lKey))
&& (!((lastObject as IDictionary<string, object>)[lKey] is ExpandoObject)))
{
return (lastObject as IDictionary<string, object>)[lKey].ToString();
}
else
{
return null;
}
}
public string[] getKeys(params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return null;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
return (lastObject as IDictionary<string, object>).Keys.ToArray();
}
else
{
return null;
}
}
public int countKeys(params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return -1;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
return (lastObject as IDictionary<string, object>).Count();
}
else
{
return -1;
}
}
public void printDebug(params string[] keys)
{
Debug.WriteLine("");
printDebugSub("", keys);
Debug.WriteLine("");
}
private void printDebugSub(string spaceStr, params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
foreach (string keyStr in (lastObject as IDictionary<string, object>).Keys.ToArray())
{
string valueStr = "";
if (!((lastObject as IDictionary<string, object>)[keyStr] is ExpandoObject))
{
valueStr = " = " + (lastObject as IDictionary<string, object>)[keyStr].ToString();
}
Debug.WriteLine(spaceStr + keyStr + valueStr);
List<string> lst = keys.ToList();
lst.Add(keyStr);
printDebugSub(spaceStr.Trim() + "---- ", lst.ToArray());
}
}
else
{
return;
}
}
}
Related
I'm trying to parse huge json file to 2d array.
I can parse. But required memory is almost 10times.
My sample.json file has 100,000 rows, each with a different item.
If sample.json is 500MB this code need 5GB.
How can i reduce memory usage?
I use Newtonsoft.Json, .Net6.0
Read from json
static void Read()
{
List<Dictionary<string, string>> rows = new List<Dictionary<string, string>>();
string path = #"D:\small.json";
using (FileStream fsRead = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bsRead = new BufferedStream(fsRead))
using (StreamReader srRead = new StreamReader(bsRead))
{
string? line;
while ((line = srRead.ReadLine()) != null)
{
JObject jsonObject = JObject.Parse(line);
MakeRowData(jsonObject, out var row);
rows.Add(row);
}
}
}
Make row
private static void MakeRowData(JObject jsonData, out Dictionary<string, string> row)
{
Dictionary<string, string> output = new Dictionary<string, string>();
foreach (var item in jsonData)
{
int childSize = 0;
if (item.Value != null)
{
childSize = item.Value.Children().Count();
///if Item has child, explore deep
if (childSize > 0)
{
ExploreChild(item.Value, ref output);
}
///or not just add new item
else
{
string str = item.Value.ToString();
output[item.Key] = str ?? "";
}
}
}
row = output;
}
private static void ExploreChild(JToken jToken, ref Dictionary<string, string> row)
{
foreach (var item in jToken)
{
int childSize = item.Children().Count();
///if Item has child, explore deep
if (childSize > 0)
{
ExploreChild(item, ref row);
}
///or not just add new item
else
{
string path = jToken.Path.Replace('[', '(').Replace(']', ')');
string str = jToken.First.ToString();
row[path] = str?? "";
}
}
}
EDIT
Add Sample.json
It is set of json strings.
And Fields are not fixed.
Sample.json
{Field1:0,Field2:1,Field2:3}
{Field1:0,Field5:1,Field6:3}
{Field1:0,Field7:1,Field9:3}
{Field1:0,Field13:1,Field50:3,Field57:3}
...
You can try replacing the recursive exploring children with the iterative one. Something like this:
private static void MakeRowData(JObject jsonData, out Dictionary<string, string> row)
{
Dictionary<string, string> output = new Dictionary<string, string>();
foreach (var item in jsonData)
{
if (item.Value != null)
{
///if Item has child, explore deep
if (item.Value.HasValues)
{
var queue = new Queue<JToken>();
queue.Enqueue(item.Value);
while (queue.Any())
{
var currItem = queue.Dequeue();
if (currItem.HasValues)
{
foreach(var child in item)
queue.Enqueue(child);
}
else
{
// add item without children to row here
}
}
}
///or not just add new item
else
{
string str = item.Value.ToString();
output[item.Key] = str ?? "";
}
}
}
row = output;
}
Recursive calls, unless it is a tail recursion, keep the stack of a method they were called from. This can lead to extensive memory usage.
I have to send a variables Json to Mailgun but it only accepts the curly braces format when using multi level json files. So,
How can I pass from this:
{ "vehicle.type": "car"}
To this, with C#
{"vehicle": {"type": "car"}}
Having into consideration that sometimes it could be up to 3 nested elements. Like element1.element2.element3: value
Here is what I recommend.
note: I am using the Newtonsoft.Json library available via Nuget, if you are using .NET Core, you can use the built in System.Text.Json library.
Because we have multiple properties in the object with flattened property keys, qualified with .s and we need to convert these properties into a hierarchical, nested JSON structure, merging siblings appropriately at each level, a simple string replacement is neither safe nor effective.
Therefore, the approach here will be to parse the flattened property keys, such as "hospital.hospitalExtraData1.Street" recursively inferring and creating a hierarchy of nested objects.
Let's begin
var originalJson = #"{
""hospital.Name"": ""BestOneEver"",
""hospital.Estatus"": ""Active"",
""hospital.hospitalExtraData1.Street"": ""43"",
""hospital.hospitalExtraData1.Color"": ""Blue"",
""hospital.hospitalExtraData1.hospitalExtraData2.IsExpensive"": ""No"",
""hospital.hospitalExtraData1.hospitalExtraData2.Works24Hrs"": ""Yes"",
""patient.Name"": ""Leonel Messi"",
""patient.Age"": ""23""
}";
var original = JsonConvert.DeserializeObject<IDictionary<string, object>>(originalJson);
Now we have an object model we can work with and restructure.
We will do this using recursion
var original = JsonConvert.DeserializeObject<IDictionary<string, object>>(originalJson);
IDictionary<string, object> Expand(IDictionary<string, object> input)
{
var result = new Dictionary<string, object>();
foreach (var property in input)
{
var (key, remainder) = ParseKey(property.Key);
if (!result.ContainsKey(key))
{
result[key] = remainder != null
? Expand(new Dictionary<string, object>
{
[remainder] = property.Value
})
: property.Value;
}
else if (result[key] is IDictionary<string, object> inner)
{
inner[remainder] = property.Value;
result[key] = Expand(inner);
}
else
{
result[key] = property.Value;
}
}
return result;
}
(string key, string remainder) ParseKey(string key)
{
var dotIndex = key.IndexOf('.');
if (dotIndex != -1)
{
return (key.Substring(0, dotIndex), key.Substring(dotIndex + 1));
}
return (key, null);
}
var expanded = Expand(original);
var expandedJson = JsonConvert.SerializeObject(expanded, Newtonsoft.Json.Formatting.Indented);
Result:
{
"hospital": {
"Name": "BestOneEver",
"Estatus": "Active",
"hospitalExtraData1": {
"Street": "43",
"Color": "Blue",
"hospitalExtraData2": {
"IsExpensive": "No",
"Works24Hrs": "Yes"
}
}
},
"patient": {
"Name": "Leonel Messi",
"Age": "23"
}
}
Here is tricky way using string replacement.
replace for any dot(.) with this (": {") and add close tag (}) at the end for every dot(.) count. Good luck!
Try This:
IDictionary<string, object> Expand(IDictionary<string, object> d)
{
var result = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> item in d)
{
var segments = item.Key.Split('.');
if (segments.Length > 1)
{
if (result.ContainsKey(segments[0]))
{
dynamic obj = new ExpandoObject();
obj = result[segments[0]];
IDictionary<string, object> myObj = obj;
myObj.Add(string.Join(".", segments.Skip(1)), item.Value);
result[segments[0]] = Expand(myObj);
}
else
{
result[segments[0]] = Expand(new Dictionary<string, object>
{
[string.Join(".", segments.Skip(1))] = item.Value
});
}
}
else
{
result[segments[0]] = item.Value;
}
}
return result;
}
how to convert :
A List :
var list = new List<string>(){"str1","str2"}
to a anonymous object :
var anonymousObject = new {str1 = "str1",str2 = "str2"}
during runtime
You can use the ExpandoObject which will give you the feature of dynamic type.
var list = new List<string>() { "str1", "str2" };
ExpandoObject obj = new ExpandoObject();
var store = (IDictionary<string, object>)obj;
list.ForEach(x => store.Add(x, x));
dynamic lst = obj;
var val = lst.str1; // Test
You can also use extension method represented below (from here).
Because converting list to dynamic object by iterating on items manually can be painful when there is many situations like this in your application.
You can use this extension method like this:
dynamic list = new List<string>() { "str1", "str2" }
.ToDictionary(dd => dd, dd => (object)dd)
.ToExpando();
The extension method:
public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;
// go through the items in the dictionary and copy over the key value pairs)
foreach (var kvp in dictionary)
{
// if the value can also be turned into an ExpandoObject, then do it!
if (kvp.Value is IDictionary<string, object>)
{
var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key, expandoValue);
}
else if (kvp.Value is ICollection)
{
// iterate through the collection and convert any strin-object dictionaries
// along the way into expando objects
var itemList = new List<object>();
foreach (var item in (ICollection)kvp.Value)
{
if (item is IDictionary<string, object>)
{
var expandoItem = ((IDictionary<string, object>)item).ToExpando();
itemList.Add(expandoItem);
}
else
{
itemList.Add(item);
}
}
expandoDic.Add(kvp.Key, itemList);
}
else
{
expandoDic.Add(kvp);
}
}
return expando;
}
I have to sort a namevaluecollection(Items usually 5 to 15) Against an enum(having items more than 60). Right now I am using this extension function, Anyone have better idea to write this code....
public static NameValueCollection Sort(this NameValueCollection queryString, Type orderByEnumType, bool excludeZeroValues)
{
NameValueCollection _processedQueryString = HttpUtility.ParseQueryString("");
if (queryString.HasKeys())
{
SortedList<int, KeyValuePair<string, string>> querySortedList = new SortedList<int, KeyValuePair<string, string>>();
string[] enumKeys = Enum.GetNames(orderByEnumType);
int counter = 1000;
foreach (string key in queryString)
{
string value = queryString[key];
if (enumKeys.Contains(key, StringComparer.CurrentCultureIgnoreCase))
{
int order = (int)Enum.Parse(orderByEnumType, key, true);
querySortedList.Add(order, new KeyValuePair<string, string>(key, value));
}
else
{
querySortedList.Add(counter, new KeyValuePair<string, string>(key, value));
counter++;
}
}
foreach (KeyValuePair<int, KeyValuePair<string, string>> kvp in querySortedList)
{
if (!kvp.Value.Value.IsNullOrEmpty() && !kvp.Value.Key.IsNullOrEmpty())
{
if (!excludeZeroValues || kvp.Value.Value != "0")
{
_processedQueryString.Add(kvp.Value.Key, System.Web.HttpUtility.UrlEncode(kvp.Value.Value));
}
}
}
}
return _processedQueryString;
}
This works like this
public enum OrderEnum
{
key1=1,
key2=20,
key3=3,
//note
key4=100,
key5=2,
key6=6,
key7,
key8,
key9
}
public void Test()
{
NameValueCollection col1 = new NameValueCollection();
col1.Add("key1", "value1");
col1.Add("key9", "value1");
col1.Add("key3", "value1");
col1.Add("key5", "value1");
Response.Write(col1.Sort(typeof(OrderEnum)).ToString());
//out put: key1=value1&key5=value1&key3=value1&key9=value1
}
This is should also work
public void Test2()
{
NameValueCollection col1 = new NameValueCollection();
col1.Add("key1", "value1");
col1.Add("key-x", "value1");
col1.Add("key-y", "value1");
col1.Add("key9", "value1");
col1.Add("key3", "value1");
col1.Add("key5", "value1");
col1.Add("key-z", "value1");
Response.Write(col1.Sort(typeof(OrderEnum)).ToString());
//out put: key1=value1&key5=value1&key3=value1&key9=value1&key-x=value1&key-y=value1&key-z=value1
}
I think its better to convert your namevaluecollection into List of keyvaluepairs and apply a simple LINQ order by operation, thats quick and simple.
Add a new extension method to convert your namevaluecoll into list of keyvaluepairs
public static List<KeyValuePair<string, string>> ToPairs(this System.Collections.Specialized.NameValueCollection collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key])).ToList();
}
And just apply the linq order by over this object, something like this
System.Collections.Specialized.NameValueCollection col1= new System.Collections.Specialized.NameValueCollection();
col1.Add("key1", "value1");
col1.Add("key-x", "value2");
col1.Add("key-y", "value3");
col1.Add("key9", "value4");
col1.Add("key3", "value5");
col1.Add("key5", "value6");
col1.Add("key-z", "value7");
var nvc = col1.ToPairs();
// To order the items based on key in descending order
var orderedbykey=nvc.OrderByDescending(x => x.Key).ToList();
// To order the items based on value in descending order
var orderedbyval=nvc.OrderByDescending(x => x.Value).ToList();
//or order by ur custom enum key
var orderbyEnumKeys = colc.OrderBy(x =>
{
int en;
try
{
en = (int)Enum.Parse(typeof(OrderEnum), x.Key);
}
catch (Exception ex)
{
return int.MaxValue;
}
return en;
}).ToList();
Hope this helps..
I finally Came to conclusion with this solution
public static NameValueCollection SortByEnum<TEnum>(this NameValueCollection source) where TEnum : struct
{
var orderedKeys = source.Keys.Cast<string>().OrderBy(k => ((Enum.IsDefined(typeof(TEnum), k)) ? ((int)Enum.Parse(typeof(TEnum), k)) : int.MaxValue));
var ordered = HttpUtility.ParseQueryString("");
foreach (var key in orderedKeys)
{
ordered.Add(key, source[key]);
}
return ordered;
}
This will resolve all my issues
Thanks #thomas #ramesh
You could do something like that :
public static NameValueCollection SortByEnum<TEnum>(this NameValueCollection source) where TEnum : struct
{
var orderedKeys = source.Keys.Cast<string>().OrderBy(k => Enum.IsDefined(typeof(TEnum), k) ? Convert.ToInt32(Enum.Parse(typeof(TEnum), k)) : int.MaxValue);
var ordered = new NameValueCollection();
foreach(var key in orderedKeys) ordered.Add(key, source[key]);
return ordered;
}
I wrote a code in C# that maps logical drives to their physical disks, using WMI (System.Management).
The code working perfectly, but slow like hell.
In my machine (Windows 7 x64, Dual-Core with 3 GB RAM) it runs as least 1 second.
1 second is too slow for me, even 0.1 is more than enough to accomplish.
I more than sore that this functionallity can be done in less than 0.1 second.
Is there any Win32API functions that can help?
Any other suggestions?
this is my code so far:
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
using (ManagementClass diskDriveClass = new ManagementClass(#"Win32_Diskdrive"))
{
using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
{
foreach (ManagementObject diskDrive in diskDrives)
{
string deviceId = (string)diskDrive["DeviceId"];
Dictionary<string, string> logicalDisksResults = new Dictionary<string, string>();
Trace.WriteLine(deviceId);
using (ManagementObjectCollection relatedPartitions = diskDrive.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject relatedPartition in relatedPartitions)
{
Trace.WriteLine("-\t" + relatedPartition["Name"]);
using (ManagementObjectCollection relatedLogicalDisks = relatedPartition.GetRelated("Win32_LogicalDisk"))
{
foreach (ManagementBaseObject relatedLogicalDisk in
relatedLogicalDisks)
{
Trace.WriteLine("\t-\t" + relatedLogicalDisk["Name"] + " " + relatedLogicalDisk["FileSystem"]);
logicalDisksResults.Add((string)relatedLogicalDisk["Name"], (string)relatedLogicalDisk["FileSystem"]);
}
}
}
}
results.Add(logicalDisksResults);
}
}
}
Well here is some code which at least on my system runs (from an objective point of view) quicker and gives the same results. As the list of drives is barely likely to change on a second by second basis I am not sure why you really care so much, but anyway, see if this makes you happier. You can speed it slightly by removing the code getting Win32_DiskDrive at the start, good luck making it run in 0.1s though :)
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string,Dictionary<string,string>>();
ManagementClass diskPartMap = null;
ManagementObjectCollection diskPartIns = null;
ManagementClass partLogicalMap = null;
ManagementObjectCollection partLogicalIns = null;
try
{
using (ManagementClass diskDriveClass = new ManagementClass("Win32_Diskdrive"))
{
using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
{
foreach (ManagementObject diskDrive in diskDrives)
{
results.Add((string)diskDrive["DeviceId"], new Dictionary<string, string>());
}
}
}
Dictionary<string, ManagementObject> partToDisk = new Dictionary<string, ManagementObject>();
Dictionary<string, ManagementObject> partToLogical = new Dictionary<string, ManagementObject>();
diskPartMap = new ManagementClass("Win32_DiskDriveToDiskPartition");
diskPartIns = diskPartMap.GetInstances();
foreach (ManagementObject diskDrive in diskPartIns)
{
ManagementObject o = new ManagementObject((string)diskDrive["Antecedent"]);
partToDisk.Add((string)diskDrive["Dependent"], o);
}
partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition");
partLogicalIns = partLogicalMap.GetInstances();
foreach (ManagementObject diskDrive in partLogicalIns)
{
ManagementObject o = new ManagementObject((string)diskDrive["Dependent"]);
string s = (string)diskDrive["Antecedent"];
partToLogical.Add(s, o);
}
foreach (KeyValuePair<string, ManagementObject> pair in partToDisk)
{
string deviceId = (string)pair.Value["DeviceId"];
Dictionary<string, string> dict = null;
if (!results.ContainsKey(deviceId))
{
dict = new Dictionary<string, string>();
results[deviceId] = dict;
}
else
{
dict = results[deviceId];
}
if (partToLogical.ContainsKey(pair.Key))
{
ManagementObject o = partToLogical[pair.Key];
dict.Add((string)o["Name"], (string)o["FileSystem"]);
}
}
}
finally
{
if (diskPartIns != null)
{
diskPartIns.Dispose();
diskPartIns = null;
}
if (diskPartMap != null)
{
diskPartMap.Dispose();
diskPartMap = null;
}
if (partLogicalIns != null)
{
partLogicalIns.Dispose();
partLogicalIns = null;
}
if (partLogicalMap != null)
{
partLogicalMap.Dispose();
partLogicalMap = null;
}
}
This is my final code, x23 faster than the first version, based on tyranid idea to use Win32_LogicalDiskToPartition.
private static Regex _logicalDiskNameRegex = new Regex("(?<=\")[^\"]*(?=\")");
private static Regex _partitionDiskIndexRegex = new Regex("(?<=\"Disk #)\\d+");
public static Dictionary<string, string>[] GetPhisicalHardDiskToDriveLettersMap()
{
DriveInfo[] driveInfoArr = DriveInfo.GetDrives();
DriveInfo lastDriveInfo = null;
Dictionary<string, DriveInfo> driveInfos = new Dictionary<string, DriveInfo>(driveInfoArr.Length);
foreach (DriveInfo driveInfo in driveInfoArr)
{
if (driveInfo.DriveType == DriveType.Fixed)
{
driveInfos.Add(driveInfo.Name.Substring(0, 2), driveInfo);
lastDriveInfo = driveInfo;
}
}
if (driveInfos.Count == 1 && lastDriveInfo != null)
{
return new Dictionary<string, string>[]
{
new Dictionary<string, string>()
{
{lastDriveInfo.Name.Substring(0, 2), lastDriveInfo.DriveFormat}
}
};
}
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string, Dictionary<string, string>>();
using (ManagementClass partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition"))
{
using (ManagementObjectCollection partLogicalIns = partLogicalMap.GetInstances())
{
foreach (ManagementObject diskDrive in partLogicalIns)
{
bool lazySuccess = false;
string driveName = null;
string driveFileSystem = null;
string physicalHardDisk = null;
string logicalDiskPath = (string)diskDrive["Dependent"];
string partitionPath = (string)diskDrive["Antecedent"];
Trace.WriteLine(logicalDiskPath);
Trace.WriteLine(partitionPath);
Match logicalDiskNameMatch = _logicalDiskNameRegex.Match(logicalDiskPath);
if (logicalDiskNameMatch.Success)
{
Match partitionDiskIndexMatch = _partitionDiskIndexRegex.Match(partitionPath);
if (partitionDiskIndexMatch.Success)
{
try
{
driveName = logicalDiskNameMatch.Value;
physicalHardDisk = partitionDiskIndexMatch.Value;
driveFileSystem = driveInfos[driveName].DriveFormat;
lazySuccess = true;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
}
if (!lazySuccess)
{
// old good code but less performance, to be on the safe side if lazy method fails.
ManagementObject logicalDiskObject = new ManagementObject(logicalDiskPath);
ManagementObject partitionObject = new ManagementObject(partitionPath);
driveName = (string)logicalDiskObject["Name"];
driveFileSystem = (string)logicalDiskObject["FileSystem"];
physicalHardDisk = partitionObject["DiskIndex"].ToString();
}
Dictionary<string, string> hardDiskDrives;
if (!results.TryGetValue(physicalHardDisk, out hardDiskDrives))
{
hardDiskDrives = new Dictionary<string, string>();
results.Add(physicalHardDisk, hardDiskDrives);
}
hardDiskDrives.Add(driveName, driveFileSystem);
}
}
}
return ToArray(results.Values);
}
I have found that the best route is to get the full data from each of the 4 classes and then do your joining with LINQ to minimize the impact on the WMI service (as it is slow under load).
As first you might think that sounds horrible, but test it out to see what I am talking about.
see this article (with code sample) about GetLogicalDrives, GetLogicalDriveStrings, GetDriveType, and GetVolumeInformation
To find physical drives, you can use FindFirstVolumeand FindNextVolume (I get "\.\Device{uiid}". Combined with GetVolumePathNamesForVolumeNameW to get the associated drive letter. Then you can get the info you want with above mentioned APIs.
If you need partition/disk numbers see DeviceIoControl to get that info
I thought you needed what is in results in your code.