Get extension from Content-Type - c#

This is a very straight forward question.
I have a Content-Type stored in the form of a string.
Ideally I'd like to infer an extension from that Content-Type without having to have a giant nasty switch case.
Is there a built in construct to achieve this?
Btw, I found this question but that goes the opposite direction from extension to content-type.

You'll want a Dictionary. This will allow you to look up an extension for a given content type:
Dictionary<string, string> extensionLookup = new Dictionary<string, string>()
{
{"ContentType1", ".ext1"},
{"ContentType2", ".ext2"},
};
You can populate the dictionary based on a database table, a file, etc. rather than hard coding the values.
Once you have the Dictionary it's as simple as:
string extension = extensionLookup[someContentType];

In the registry of my W10 box there is an extensive list mapping content-type to .extn:
[HKEY_CLASSES_ROOT\MIME\Database\Content Type]
You might like to explore the HtmlAgilityPack OSS project which has source file HtmlWeb.cs containing the following methods:
public static string GetContentTypeForExtension(string extension, string def)
public static string GetExtensionForContentType(string contentType, string def)
There is also [commented-out] Dictionary and population code:
//private static Dictionary<string, string> _mimeTypes;
// _mimeTypes = new Dictionary<string, string>();
// _mimeTypes.Add(".3dm", "x-world/x-3dmf");
// _mimeTypes.Add(".3dmf", "x-world/x-3dmf");
// ...
// _mimeTypes.Add(".zoo", "application/octet-stream");
// _mimeTypes.Add(".zsh", "text/x-script.zsh");
So you may brew your own (maybe just the common ones that YOUR app needs) for efficiency.
FYI the authoritative list of content-type values and usage is here:
www.iana.org/assignments/media-types/media-types.xhtml

Related

Is there a way to construct a deeply nested Dictionary with nice syntax and IntelliSense support?

I am trying to create an object that contains the parsed register values of a robot. I have an ASCII text file that contains representations of the variables and arrays. However, I am struggling to think of an easy way to use the deeply nested values. Ideally, the syntax to use the deeply nested objects would be something like Registers["PositionRegister"]["CurrentPosition"]["X_Coordinate"] and the dictionary would be something like this:
(There was a JSON representation here of what I wanted the dictionary to look like, but people kept suggesting JSON serialization...)
However, since I am parsing the file and constructing the object at the same time, I don't know how deep the nesting will go until the parsing is complete.
I've tried using a simple Register class that can contain a dictionary of sub-Registers:
public class Register
{
public Dictionary<string, Register>? subRegisters;
public string name { get; set; }
public string value { get; set; }
}
However, the usage turns into super unintuitive syntax like motionRegister.subRegisters["Register1"].subRegisters["SubRegister1"].subRegisters["Value1"].Value and I'm duplicating information by using the name as the key.
I've also tried using only nested Dictionaries like:
public Dictionary<string, object> CreateRegisters()
{
Dictionary<string, object> TopLevelRegisters = new();
Dictionary<string, object> SubRegisters = new();
Dictionary<string, object> SubSubRegisters = new();
SubSubRegisters.Add("SubSubElement1", "5678");
SubRegisters.Add("SubElement1", "1234");
SubRegisters.Add("SubElement2", SubSubRegisters);
SubRegisters.Add("SubElement3", "1357");
TopLevelRegisters.Add("Register1", SubRegisters);
return TopLevelRegisters;
}
but they end up being super difficult to use since IntelliSense doesn't know what the object will be until runtime. I would return it as another Dictionary, but I don't know how deep the nesting will have to go.
I'm sure that there's a simple solution, but I can't seem to find it.
The closest thing I could come up with is to
Subclass Dictionary<>, and define the subclass in terms of itself (allows for arbitrary depth, and prevents the need for what you call the "unintuitive syntax" of a sub-dictionary manifesting in the path)
Hide the existing indexer with a new implementation (allows for auto-construction of a new level)
Provide a Value property for storing the value of the leaf node.
Provide a ToString() that returns Value (allows for the elimination of .Value from the syntax in certain cases, such as concatenation of strings, WriteLine, etc.)
NOTE: A Name property is dropped altogether because the name can be determined based on the dictionary key.
This code will look something like this
public class RecursiveDictionary : Dictionary<string, RecursiveDictionary>
{
public string? Value { get; set; }
public override string? ToString() => Value;
public new RecursiveDictionary this[string key]
{
get
{
if (!TryGetValue(key, out var subDictionary))
base[key] = subDictionary = new RecursiveDictionary();
return subDictionary;
}
set => base[key] = value;
}
}
During parsing, you only have to output each path to a terminal Value or if you keep track of where you're at in the parsing, simply set the Value of the current (sub)dictionary. (Side note, it doesn't matter how you build it or whether the source is proprietary (your case), JSON, or some other format).
Here's an example construction:
var rd = new RecursiveDictionary();
rd["x"].Value = "Hi!";
rd["x"]["y"].Value = "VALUE";
rd["a"]["b"]["c"]["d"].Value = "VALUETWO";
Notice, I didn't have to allocate RecursiveDictionary for every level; this is because the get portion of the indexer does that for me.
From the static Intellisense (i.e. while program is not running), you can hover over rd and see it is a RecursiveDictionary,
hover over Value and see that it is a string,
and hover over one of the ] or [ and see that it is an indexer on the dictionary:
Now for the dynamic (runtime under debugger) I'm not going to show all the code for various accesses or the Intellisense for it, but I can emulate both in a watch window. What you see in the watch window below could just as easily been lines of Console.WriteLine(...) with you hovering over the various locations. So imagine these examples:
CAVEAT: The ToString() might give you some unexpected results depending on the situation. Are you concatenating strings, are you viewing in the debugger, are you using in a WriteLine(), are you passing a sub-dictionary to another method, etc. If that becomes problematic, then go for a slightly less terse syntax that requires you to always get the value explicitly via the Value property.

Adding data of type dynamic to dictionary

I have a code like this:
private void CreateRecord(dynamic dealerData, string methodVerb)
{
var sample = new MarketData()
{
Parameters = new Dictionary<string, string>();
}
}
I want to add dealerData to dictionary at runtime.
Can this dictionary initialization be used like this:
Parameters = JsonConvert.DeserializeObject<Dictionary<string,string>>(dealerData);
Also, I want to add one more line to this dictionary at runtime.
This is: "Verb", "PUT".
Based on the information provided, it seems like it would be easier - and better practice - to deserialize your Json into a data model. The concept you've come up with doesn't seem to be suited to holding the information you want in an easily usable way.
However, if you insist on pursuing this method, I'll assume your Json looks like:
{ "property1": "value1", "property2": "value2" }
You can deserialize your Json to a Dictionary like this:
Parameters = JsonConvert.DeserializeObject<Dictionary<string,string>>(dealerData);
Parameters.Add("Verb", methodVerb);
If your Json isn't in this format, you'll have to let me know and I'll update my answer.

Creating dictionaries with pre-defined keys C#

I'm looking for a way to define a dictionary for reuse. ie. I can create the dictionary object without having to populate it with the values I want.
Here is what I have currently (note code not tested, just example)
public Dictionary<string, string> NewEntryDictionary()
{
Dictionary<string, string> dic = new Dictionary<string, string>();
// populate key value pair
foreach(string name in Enum.GetNames(typeof(Suits))
{
dic.Add(name, "");
}
return dic;
}
The end result should be a new dictionary object with a predefined set of keys.
But I want to avoid doing it this way.
It's not really clear whether you're concerned about the amount of code you've written, or the efficiency of it. From an efficiency perspective, it's fine - it's O(N), but that's hard to avoid if you're populating a dictionary with N entries.
You can definitely make the source code shorter though, using LINQ:
public Dictionary<string, string> NewEntryDictionary()
{
return Enum.GetNames(typeof(Suits)).ToDictionary(name => name, name => "");
}
That won't be any more efficient, of course... it's just shorter code.
If you do ONLY want to save values according to your enum, use
Dictionary<Suits,String> instead of Dictionary<String,String>
Everything else, Jon already said. Use LinQ for a bit more "fancy" look. But that does not do better performance

Key Value array in C# put into parameter

Coming from PHP, I have never written C# before and I have encountered something like this in C#:
public string rule(string playerId, string action, params string[] optionalData){
...
}
and in PHP it is like this
public function rule($playerId, $action, $optionalData=array()){
...
}
In PHP I simply fill out the parameter for the $optionalData like this...
myVar->rule("123", "myAction", array('url'=>'review.com');
However in C# I am not sure how to fill the optionalData (params string[] optionalData) parameter as it is a key value parameter (like in the PHP example). My question is how do I create a key value array like the PHP that I created in my example and put into the parameter?
CoolClass cc = new CoolClass();
cc.rule("123", "myAction", ???);
I was searching google and was looking at dictionary and hashmaps etc but I am guessing it is an overkill or it does not work..
Many thanks!
When you were looking at dictionaries, you were definitely looking at the right facility.
If rule() in C# is in your own code, may I recommend changing the signature to:
public string rule(string playerId, string action, IDictionary<string, string> optionalData = new Dictionary<string, string>()){
...
}
What this allows you to do:
Operate on the values in optionalData the way that other C# programmers will expect.
The = new Dictionary<string, string>() part of the suggested method signature make the parameter truly optional. It will not be necessary when calling the method.
You can use IDictionary<T> methods to work with the data. Some syntax you should be somewhat familiar with (consider accessing by key optionalData["someString"].)
However, if rule() is not in your code, you would leave out the optionalData by simply omitting parameters. Examples of valid calls of the original C# method in your question:
rule("Bob", "load")
rule("Bob", "load", "url", "www.example.com") (In this case, optionalData[0].Equals("url", StringComparisonOptions.Ordinal) and optionalData[1].Equals("www.example.com", StringComparisonOptions.Ordinal) is true.
One thing to consider about the original method - keep in mind that rule("Bob", "load", 'url") is a valid call, and you would need to have a run-time check to make sure you had the right number of parameters. Another plus to using a Dictionary<TKey, TValue>. You may even consider writing an adapter method to the original rule(), if you can't change it.
You can use a Dictionary:
Dictionary<string,string[]>
or something like:
Dictionary<int, string[]>
I believe dictionary will work in your case.
You can use Dictionary <key_datatype, value_datatype> .
Example:
Your method definition here :
public string rule(string playerId, string action, Dictionary<string, string> optionalData){
...
}
Method call:
Dictionary<string, string> optionalData = new Dictionary<string, string>();
optionalData.Add("url", "review.com");
cc.rule("123", "myAction", optionalData);
Or
you can use DynamoObject to make it more easier to write:
dynamic optionalData = new ExpandoObject();
//The token after the dynamoObject period will be the key to the assigned value.
optionalData.url = "review.com";
cc.rule("123", "myAction", optionalData);
Your method can get the key-value pairs like this:
public string rule(string playerId, string action, dynamic optionalData)
{
...
foreach (var pair in (IDictionary<string, object>)optionalData)
{
if (group.Key == "url")
{
Console.WriteLine(group.Value);
}
else if (group.Key == "post")
{
Console.WriteLine(group.Value);
}
}
}

What is the most readable use of String.Format for long strings with many parameters?

For instance:
String login = String.Format("computer={0}&ver={1}.{2}.{3}&from={4}&realcomputername={5}&type={6}&Channels={7}&Hotkeys={8}&ID={9}\r\n",
serviceConfig.Computer,
serviceConfig.Version.Major,
serviceConfig.Version.Minor,
serviceConfig.Version.Build,
userName,
Environment.MachineName,
type,
serviceConfig.ChannelsString,
serviceConfig.HotKeysString,
serviceConfig.AlarmGroupName);
This does not make for very readable code, and as more and more parameters get added, it looks uglier and is more confusing to find which parameter goes in which slot.
I know this is a noob question, and I think I'm only asking for how to format the text to be more readable, but if there's a better way to do this, I'd like to know that too.
You could look at the StringBuilder class and split the assembly of the string over several lines.
The AppendFormat method (thanks Joel) is what you want in this case.
String login = String.Format(
"computer={0}"+
"&ver={1}.{2}.{3}"+
"&from={4}"+
"&realcomputername={5}"+
"&type={6}"+
"&Channels={7}"+
"&Hotkeys={8}"+
"&ID={9}\r\n",
serviceConfig.Computer,
serviceConfig.Version.Major,
serviceConfig.Version.Minor,
serviceConfig.Version.Build,
userName,
Environment.MachineName,
type,
serviceConfig.ChannelsString,
serviceConfig.HotKeysString,
serviceConfig.AlarmGroupName);
Assuming you can use LINQ, you can shove your arguments into a Dictionary<string, string>, then join the arguments together:
Dictionary<string, string> args = new Dictionary<string, string>
{
{"computer", serviceConfig.Computer},
{"ver", string.Format("{0}.{1}.{2}",
serviceConfig.Version.Major,
serviceConfig.Version.Minor,
serviceConfig.Version.Build)},
{"from", userName},
{"realcomputername", Environment.MachineName},
{"type", type},
{"Channels", serviceConfig.ChannelsString},
{"Hotkeys", serviceConfig.HotKeysString},
{"ID", serviceConfig.AlarmGroupName},
};
string login = string.Join("&", args.Select(arg =>
string.Format("{0}={1}", arg.Key, arg.Value)).ToArray());
This will be some miniscule amount slower and more memory-intensive than a simple string.Format, but it looks like you're about to make an HTTP request, so I can almost guarantee that it won't be the bottleneck.
That final line can also be pulled out into an extension method that you can use anytime you want to build a query string like this.
Also, it's important to note that since Dictionary does not preserve insertion order, you aren't guaranteed that the parameters in the query string will be in that exact order. That shouldn't matter, but in case it does you can replace the Dictionary with a List<KeyValuePair<string, string>> (OrderedDictionary should also work).

Categories