jeudi 28 août 2014

C#: Enum and Attributes …

 

Today I had to update a system with a new kind of device. A device setup is a bit complex and when they start they look into a configuration file and try to transform/cast some “System.Configuration.ConfigurationManager.ConnectionStrings” into their corresponding Enum value in the system.

My Enum looks like:

public enum DeviceType
{
[Description("Apple IPod")]
IPOD = 1,
[Description("Apple iPad")]
APPLE_IPAD,
[Description("Google Glass")]
GGlass,
[Description("Surface")]
MS_SURFACE,
[Description("MS Surface PRO")]
MS_SURFACE_PRO,
[Description("Unknow")]
UNKNOW = 1000
}



After the addition of the “Google Glass” device … I quickly discovered that in several place I have to add an additional else in an already too long if-else sequence to handle the conversion of the string in an Enum value.

if(MyDeviceType == Device.IPOD.ToString())
MyDeviceType = DeviceType.IPOD;
else if(MyDeviceType == Device.APPLE_IPAD.ToString())
MyDeviceType = DeviceType.APPLE_IPAD;

etc...



If think it looks like that just because too many developers doesn’t master the language  they use and first I would say that from my point of view I’m not a master but just a developer aware some useful functionalities of C# and one I like is the template and how you can explore the types/values and check if they have attribute.


So to simply, improve the code and add a bit of flexibility in the configuration string we use I decided to add an “Helpers” method in that system to definitely solve that issue.

public static class Helpers
{
public static T GetValueFromDescription<T>(string description)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
if (field.Name == description)
return (T)field.GetValue(null);

var attribute = Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute != null)
{
if (attribute.Description == description)
return (T)field.GetValue(null);
}
}
throw new ArgumentException("Not found.", "description");

}
}



As you can see, it’s really easy to read. If T is an Enum, we iterate over all field in the Enum. If the string match with a filed name (i.e “IPOD”, “APPLE_IPAD”) it’s OK, we return the field value. If it doesn’t match we look for a Description Attribute. Those attribute are really useful to provide a human readable description for Enum value, class data member, etc… So here if the config string match with a config attribute it’s also OK and due to that “IPOD” and “Apple IPod” return the same Enum value (Flexibility !).


And now if I replace all the existing if-else sequence by something like:

type = DeviceType.UNKNOW;
try
{
type = ExtensionMethods.GetValueFromDescription<DeviceType>(configuration_string);
}
catch (Exception ) //silently ...
{
type = DeviceType.UNKNOW;
}



It looks better from my point of view and next time we will a new device type all the mapping code is ready, no update to do !


The only thing I really regret is that all those cool device are only here for the example and I don’t have or work with them …. Snif Snif !

vendredi 1 août 2014

A coding exercise: The Caesar’s Cipher

 

As one of my holidays book is “Digital Fortress” from the very well-known Dan Brown (he is the author of “The Da Vinci code”) I found interesting to implement by my self some of the message encryption method he describe in that book.

 

To describe a bit the story, the “Digital Fortress” in an unbreakable cipher and it’s potential availability is a cataclysm for the NSA. And in its introduction the author present the NSA and what the crypto science is.

 

He say that the “Caesar’s Cipher” was one of the first known ciphering technic. And after looking Wikipedia it looks like the method he described wasn’t the same. The “Caesar’s Cypher” is typically a method based on a fixed alphabet shift, but he talked about a box based method using a “magic square” (search for the “Caesar’s box cipher”).

My code is really simple, in the first implementation I made I just represented spaces by ‘_’ but you can also choose to remove all spaces using:

inputMsg.erase(remove(inputMsg.begin(), inputMsg.end(), ' '), inputMsg.end());

The trick is to find the root X of the message length and after you draw a square of X*X, write your message character by character (1 per cell) from the top-left corner to bottom-right corner and transpose the table.

auto inL = inputMsg.size();
auto sqrtInL = (unsigned int)(sqrt(inL) + .5);
auto codeL = sqrtInL * sqrtInL;

out = string(codeL, '_');
for(auto ui = 0 ; ui < sqrtInL ; ++ui) {
for(auto = 0 ; uj < sqrtInL ; ++uj) {
if(ui*sqrtInL+uj < inL) {
out[uj*sqrtInL+ui] = (in[ui*sqrtInL+uj] != ' ') ? in[ui*sqrtInL+uj] : '_' ;
}
}
}