I have the following structure and would like a solution with both benefits from the following two classes. The first class is using strings and strongly typed members:
public class UserSessionData
{
private string Get(string key)
{
throw new NotImplementedException("TODO: Get from external source");
}
private void Set(string key, string value)
{
throw new NotImplementedException("TODO: Set in external source");
}
public string CustomerNumber {
get { return Get("CustomerNumber"); }
set { Set("CustomerNumber", value); }
}
public string FirstName {
get { return Get("FirstName"); }
set { Set("FirstName", value); }
}
public string LastName {
get { return Get("LastName"); }
set { Set("LastName", value); }
}
// ... a couple of hundreds of these
}
I can imagine an alternative being a Get
and Set
method with an enum
parameter. Here is the second class:
public class UserSessionData
{
public enum What {
CustomerNumber, FirstName, LastName, // ...
}
public string Get (What what) { return MyExternalSource(what); }
public string Set (What what, string value) { return MyExternalSource(what); }
}
But the consumer side of class #2 is not pretty:UserSessionData.Get(UserSessionData.What.CustomerNumber)
Compare it to the first class: UserSessionData.CustomerNumber
Is there a strongly typed way of calling the Get and Set methods in my first class example? Stated another way: How do I get the benefits from both classes, i.e. the maintainability of strongly typed members and a nice-looking syntax?
If you use .Net 4.5 or newer you can make use of CallerMemberNameAttribute so you can call it like this:
public string CustomerNumber {
get { return Get(); }
}
To make this work, modify the Get method by adding the attribute to the parameter:
private string Get([CallerMemberName] string key)
{
...
}
Performance notice: The compiler will insert a string as parameter at the calling site, so this is fast.
If you use .Net 4.0 or earlier, you can still use strongly typed property names instead of typing strings manually, but you need to implement a method like this to extract the property name from an Expression, and then you can call it using an expression:
public string CustomerNumber {
get { return Get(() => this.CustomerNumber ); }
}
The setters can be implemented in the same fashion.
Performance notice: The string is extracted at runtime, so this is slower than using CallerMemberNameAttribute.
You can use a T4 template to generate the class. In the T4 template you just name all the properties - you could get them through reflection from an enum, too, but using a string array is simpler.
Add New Item -> Text template
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<# var properties = new string [] {
"CustomerNumber", // This is where you define the properties
"FirstName",
"LastName"
}; #>
class UserSessionData {
<#
foreach (string propertyName in properties)
{ #>
public string <#= propertyName #>{
get { return Get("<#= propertyName #>"); }
set { Set("<#= propertyName #>", value); }
}
<# } #>
}
More info @ Design-Time Code Generation by using T4 Text Templates
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With