Checking string format at compile time in C# - c#

In my code there are several strings which are used as keys to access resources. These keys have a specific format, e.g.
string key = "ABC123";
Currently, all these keys are stored as strings, but I'd like to make things more robust and type-safe. Ideally, I'd like to check the strings are in the correct format at compile time.
The next stage is to create a ResourceKey class that is initialised from a string. I can then check the format of the string at runtime, e.g.
ResourceKey key = "ABC123";
where ResourceKey is defined as:
using System.Diagnostics;
using System.Text.RegularExpressions;
class ResourceKey
{
public string Key { get; set; }
public static implicit operator ResourceKey (string s)
{
Debug.Assert(Regex.IsMatch(s, #"^[A-Z]{3}[0-9]{3}$"));
return new ResourceKey () { Key = s };
}
}
What I'd really like to do is to have a sort of compile-time assert so that the program fails to build if anyone tries to use an invalid key. e.g.
ResourceKey k1 = "ABC123"; // compiles
ResourceKey k2 = "DEF456"; // compiles
ResourceKey k3 = "hello world"; // error at compile time
Is there any way to achieve this?
Thanks

You could check the values with a unit test. One of my co-workers had to do something similar to this in a project where we needed to ensure that all classes in a certain namespace had certain attributes applied to them.
Run the unit tests with your build (you do that anyways right? :) or as part of an integration build. This will keep your source cleaner as well as you won't have to introduce code that does assertions.

I believe that I would add a Settings class and store them there instead of creating a new type. The Settings class can be backed by an application configuration file that will make them easier to change via configuration file changes if needed. If you don't specify them in the configuration file, though, it will use the values you set as defaults.
I'd also go the unit test route. You'll need to use the InternalsVisibleTo attribute in your Assembly.cs file since I don't think that Settings can be used outside the project if you don't.

Do you really want these keys hardcoded into your app? Wouldn't it be better to have them in a config file? Then if there are any problems post compile, it's simply a runtime configuration issue.

AdamRalph has a point but the counter point also works, if you get it right at compile time, you will never have run-time config issues (assuming the correct values can't change)
Outside that, C#'s compile time abilities are absolute Junk. Their is next to nothing that can be done at compile time. The best available I known of is the template where clause. If I had to guess, I'd say that this is a intentional design choice by Anders Hejlsberg as it seems to match with the rest of the language
Andrew Hare's point about unittests + reflection is about as good as I'd expect. A co worker of mine uses that to test that any class that could be used in a particular cases correctly implemented some protocol.

If the keys are named according to the same rules as C# identifiers, or perhaps even more limiting, and known and finite, you could use an enum:
public enum ResourceKeys
{
ABC123,
DEF456
}

Related

what will be the Regular Expression to get all the property and variables names of a class in c#?

What will be the Regular Expression to get all the property and variables names of any class in c#, I want to parse the *.cs file. that is i want to select any *.cs file as input and it should get the property name of that selected class, as an output.
can any one help!!!....would appreciate for any help i tried very much but not got the actual result every time class name is coming instead of property.
thanks
Jack
There's no way you're going to be able to get exactly what you want with a regular expression because you need semantic context, not just string parsing.
For example, a good first attempt at finding all of the field and property definitions in a C# file might go something like this
^\s*(?:(?:private|public|protected|internal)\s+)?(?:static\s+)?(?:readonly\s+)?(\w+)\s+(\w+)\s*[^(]
That will match properties (public int Foo {...}) and fields (private int foo;) but not methods (protected void Bar()).
The problem is that a regex engine has no concept of the context within which those tokens appear. It will match both foo and bar in this code:
int foo;
void Stuff()
{
int bar;
}
If you happen to know that your code file follows some coding standards, you may have more luck. For example, if you enforce a style rule that all class members must have access specifiers, then you can make the private/public/etc part of that regex non-optional; since those are only permitted at the class level, it will filter out local variables.
There are other options, none of them too attractive at first glance. There is persistent talk from the C# dev team about exposing the C# compiler as a service in some future version of .NET, which would be perfect here, but I wouldn't expect that any time soon. You could purchase a third-party C# parser/analyzer like this one (caveat: I have zero experience with that, it's just the first Google hit). You could try compiling the .cs file using csc and examining the IL, but you'd need to know all of the third-party references.

Integration Test for All References of a Method Invocation

So, I've been searching around on the internet for a bit, trying to see if someone has already invented the wheel here. What I want to do is write an integration test that will parse the current project, find all references to a certain method, find it's arguments, and then check the database for that argument. For example:
public interface IContentProvider
{
ContentItem GetContentFor(string descriptor);
}
public class ContentProvider : IContentProvider
{
public virtual ContentItem GetContentFor(string descriptor)
{
// Fetches Content from Database for descriptor and returns in
}
}
Any other class will get an IContentProvider injected into their constructor using IOC, such that they could write something like:
contentProvider.GetContentFor("SomeDescriptor");
contentProvider.GetContentFor("SomeOtherDescriptor");
Basically, the unit test finds all these references, find the set of text ["SomeDescriptor", "SomeOtherDescriptor"], and then I can check the database to make sure I have rows defined for those descriptors. Furthermore, the descriptors are hard coded.
I could make an enum value for all descriptors, but the enum would have thousands of possible options, and that seems like kinda a hack.
Now, this link on SO: How I can get all reference with Reflection + C# basically says it's impossible without some very advanced IL parsing. To clarify; I don't need Reflector or anything - it's just to be an automated test I can run so that if any other developers on my team check in code that calls for this content without creating the DB record, the test will fail.
Is this possible? If so, does anyone have a resource to look at or sample code to modify?
EDIT: Alternatively, perhaps a different method of doing this VS trying to find all references? The end result is I want a test to fail when the record doesnt exist.
This will be very difficult: your program may compute the value of the descriptor, which will mean your test is able to know which value are possible without executing said code.
I would suggest to change the way you program here, by using an enum type, or coding using the type safe enum pattern. This way, each and every use of a GetContentFor will be safe: the argument is part of the enum, and the languages type checker performs the check.
Your test can then easily iterate on the different enum fields, and check they are all declared in your database, very easily.
Adding a new content key requires editing the enum, but this is a small inconvenient you can live with, as it help a log ensuring all calls are safe.

Which is the better way to avoid magic string keys? Using string const keys in a class or using enumeration?

My idea is to avoid magic string keys in my Asp.Net MVC application.
To do so, I want to create string constant keys to be shared in the application.
For example, I can write TempData[MyClass.Message] or TempData[MyEnum.Message.ToString()] instead of TempData["Message"].
public class MyClass
{
public const string Message = "Message";
}
and
public enum MyEnum
{
Message,
Others
}
My questions are: Which is the better way to avoid magic string keys? Using string const keys in a class or using enumeration together with ToString()?
It is up to preference and usage.
You are able to accept the enumerated values in a strongly typed way:
public void SomeFunction(MyEnum someValue)
{
}
Or
TempData[MyEnum.Message]
With const strings, you can't.
You also have a built-in way to enumerate the values in an enum.
There is a third option which you haven't presented, and that is to place your "constants" in your configuration settings (App.Config). This will let you configure them after compile time. You might not need this now, but you might in the future, so it is worth considering.
One of these may be better for globalization purposes. I'm not sure which, since I've never globalized an app. Whichever works in satellite assemblies, I assume.
Basically, it comes down to what TempData is, and how you intend to use it.
You should go for const strings as it can containt spaces/special chars as well, if those are your requirements. Otherwise change TempData to Dictionary<MyEnum,object> which is better approach.
I know this has been answered, but I want to throw in my thoughts here. You're focusing too closely on the mechanics and not the problem you're having - which is "how do I get away from breaking my application when I decide TempData["Message"] should actually be Session["Alert"]" (or something like that.
Magic strings do not apply to dictionary keys - they apply to messages sent to routine that does something based on the string value. Something like "SetStatus('current')" would be magical.
What you want to do here is to use a centralized method for handling messaging. Create yourself a helper class and call it "Messaging" if you like - ir get all Railsy and call it "Flash". Then, you could do something groovy like "Flash.Message("Hi there")" - this keeps the mechanism hidden (as it should be) and you're not worrying about those silly dictionary keys.
You can also expand this - "Flash.Alert('Oh NO!')" - etc.

Removing literal strings in .net code

What have you done to remove (Helpers/extension methods) string literal in code?
e.g. I have nhibernate search criteria code like this all over the place.
Expression.Eq("Status", LoginStatus.LoggedIn),
“Status” being the property of an entity object used as a string in the case.
Update: Primary reason in this case is to enable refactoring. If I write a helper method which reflects the object and gets the value, will make the above expression strongly typed.
This is what "Resources" and "Settings" is for. You can find this by right clicking your project in Visual Studio and clicking "Properties", then going to the "Resources" or "Settings" tab.
For pre-built resources that won't change often, use resources. For things you want to be configurable use Settings instead because it will auto-generate blocks of configuration for your App.config. You will still need to manually copy and paste these values if you do not want to use the defaults.
The nice thing about both is that VS will build a nice static class with properties you can use throughout your code. VS will maintain the class and resources for you dynamically as long as you continue to use the wizard.
I'll usually declare them as constants, or, if I have groups of related strings, I'll create an enum instead.
Either way, at least they have a descriptive name attached to them (instead of using "magic strings"), and their use will always be consistent.
In the past, I've used CodeRush (or your favourite refactoring tool) to convert to a const string in the class, and then moved said const strings to be public members of the entity class to which they apply.
The real answer here, if you're looking to get your code less brittle in the face of refactoring is to get out of the strings business, and use Linq 4/to NHibernate, but you'd have to research whether it's completeness is sufficeint for your purposes.
Realized that I could do this the Expression trees way. Using Code as data!
Something like this
protected IList<T> _FindByProperty<TResult>(Expression<Func<T, TResult>> expression, TResult value)
{
return _FindByProperty((expression.Body as MemberExpression).Member.Name, value);
}
IList<User> costCenters = _FindByProperty( user=> user.Name, "name");
Credits: http://suryagaddipati.wordpress.com/2009/03/14/code-as-data-in-c-taking-advantage-of-expression-trees/
This is related to a lot questions in the expression-trees tag.
I use a similar approach as Cherian. I got my idea from the FluentNhibernate's ReflectionHelper.
The principle is to use expression trees and then you could just put in a x => x.Status expression. The method would return the property name as string.
In fact, you could also just use FluentNHibernate? However, I don't know if their querying model is evenly extensive as their mapping interfaces...

Where to store configuration information

I have a console application that I am rebuilding from C to C#. This application has to be able to support the legacy method of storing information like parameters from a command-line and parameters from a file (called the system parameters) that customize each run. The system parameters file is in plain-text with a simple key-value structure.
My questions are:
Should I combine these different parameters into a single Configuration object?
How would I call this configuration object from the code to store parameters?
How would I call this configuration object from the code to retrieve parameters?
Should this object be strongly-typed?
I will need access to this structure from a lot of different places in the code. What is the most elegant way to retrieve the values in the object without passing the object itself around everywhere?
I have a feeling that it should be a single, strongly-typed object and that it should be an instantiated object that is retrieved from a repository with a static retrieval method however I really want validation of this method.
I would use a single configuration object like the following:
using System;
using System.IO;
using System.Reflection;
public sealed class Setting {
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
static readonly string SETTINGS = "Settings.ini";
static readonly Setting instance = new Setting();
Setting() {}
static Setting() {
string property = "";
string[] settings = File.ReadAllLines(SETTINGS);
foreach (string s in settings)
try {
string[] split = s.Split(new char[] { ':' }, 2);
if (split.Length != 2)
continue;
property = split[0].Trim();
string value = split[1].Trim();
PropertyInfo propInfo = instance.GetType().GetProperty(property);
switch (propInfo.PropertyType.Name) {
case "Int32":
propInfo.SetValue(null, Convert.ToInt32(value), null);
break;
case "String":
propInfo.SetValue(null, value, null);
break;
}
} catch {
throw new Exception("Invalid setting '" + property + "'");
}
}
}
Since this is a singleton, it will create one and only one instance of itself the first time a public static property is referenced from the Setting object.
When the object is created, it reads from the Settings.ini file. The settings file is a plain-text file with a simple key : value structure that might look like this:
FrameMax : 12
VideoDir : C:\Videos\Best
The object uses reflection to discover each property and to store its initial value. In this example, two properties have been defined:
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
The code as written handles Int32 and String types. By adding additional case statements to the switch statement, you could easily add support for types like Float and Decimal.
To change a setting, you would use something like:
Setting.FrameMax = 5;
To retrieve a setting, you would use something like:
if (Setting.FrameMax > 10) ...
You'll notice that all the properties are strongly-typed. Also, you don't have to pass the Setting object around, as all the Setting properties are static and always available everywhere.
I hope this idea is helpful.
I like using Settings. These can be generated automatically either by creating a settings file using the Add New File dialog box, or by adding a default settings file from project properties.
Each setting may be in user or application scope, which controls whether or not the user can change them or they are restricted to their default values. They are easily saved with the Save() method and loaded automatically into the static Default property.
This class seems to be for application or user-based settings. I'm looking for per-run settings. Would you still recommend using this class in that case? – x97mdr
Yes. If you have both user/application based settings and per-run settings you should use two different classes - the normal (saved) settings and the per-run settings.
As long as you don't save the per-run settings, you should be safe and settings are still quite easy to use. These are static settings though. If the same application run needs several instances - this is the wrong approach.
I find that whenever I have to deal with a legacy system, sticking with the old format almost always works best. Often times there are other people using the legacy formats for other tasks (like automation of the app, for example), so if you recode the way the application handles inputs, you might break other systems.
On the other hand, if you are pretty confident that you know all the people using the system, and they tell you that they don't care if you change these types of things, I would probably move everything to XML. Besides all the nice features of XML from an application point of view (like being in ASCII so it's easily modified by humans, being self-documenting, etc ...), XML is also time-saving, in that you don't have to write your own I/O or parser. There's already a wide variety of libraries out there, particularly in .NET 3.0/3.5, that do very well. (As you're moving to C#, I'm guessing you're already thinking along these lines :)
So ultimately, you'd have to base your decision on cost-to-implement: if you lower your cost of implementation by moving to XML or similar, make sure that you don't raise other people's cost of implementation to move to your new application framework.
Good luck!
XmlDocument - you can generate a class definition using XSD.exe

Categories

Resources