How should I design string validation classes in C#? - c#

I have several applications within my domain that accept similar inputs in text fields. Each application implements its own validation. I want to bring that functionality into a class library so that rather than re-inventing the wheel on each project, our developers can quickly implement the validation library, and move on.
I'm not the best when it comes to OO design. What I need is the ability for a user to enter an arbitrary string, and then for the validation library to check it against the known types to make sure that it matches one of them. Should I build an interface and make each type of string a class that implements that interface? (seems wrong since I won't know the type when I read in the string). I could use some help identifying a pattern for this.
Thanks.

I've always been a fan of Fluent Validation for .Net. If it's more robust then you need, it's functionality is easy enough to mimic on your own.
If you're interested, here's a link to my very simple validation class. It's similar in usage to Fluent Validation, but uses lambdas to create the validation assertions. Here's a quick example of how to use it:
public class Person
{
public Person(int age){ Age = age; }
public int Age{ get; set;}
}
public class PersonValidator : AbstractValidator
{
public PersonValidator()
{
RuleFor(p => p.Age >= 0,
() => new ArgumentOutOfRangeException(
"Age must be greater than or equal to zero."
));
}
}
public class Example
{
void exampleUsage()
{
var john = new Person(28);
var jane = new Person(-29);
var personValidator = new PersonValidator();
var johnsResult = personValidator.Validate(john);
var janesResult = personValidator.Validate(jane);
displayResult(johnsResult);
displayResult(janesResult);
}
void displayResult(ValidationResult result)
{
if(!result.IsValid)
Console.WriteLine("Is valid");
else
Console.WriteLine(result.Exception.GetType());
}
}
(see source code for a more thorough example).
Output:
Is valid
System.ArgumentOutOfRangeException

Each application implements its own validation. I want to bring that functionality into a class library so that rather than re-inventing the wheel on each project, our developers can quickly implement the validation library, and move on.
Your problem seems similar to custom NUnit constraints.
NUnit allows something they call a constraint-based assertion model, and allow the user to create custom constraints, saying whether or not a given object satisfies the criteria of that constraint.
Using an object-based constraint model is superior to a purely function-based constraint model:
It lets you aggregate sub-constraints to evaluate a higher level constraint.
It lets you provide diagnostic information as to why a specific constraint doesn't match your input data.
This sounds fancy, but constraints are just functions that take a parameter of your desired type, returns true if it matches, and false if it doesn't.
Adapting it to your problem
What I need is the ability for a user to enter an arbitrary string, and then for the validation library to check it against the known types to make sure that it matches one of them.
You don't actually have to build assertions out of your constraints. You could evaluate constraints without throwing exceptions, and do your classifications first.
But I don't recommend you do any automatic classification. I recommend you attach a specific constraint to a specific input, rather than trying to match all available constraints. Pass in the string to that constraint, and call it done.
If you need to do this for higher level objects, build a constraint for the higher level object that uses specific (existing) constraints for each of its sub fields, as well as doing cross-field constraint validation.
When you're done, you can aggregate all constraint violations to the top level, and have your validation logic throw an exception containing all the violations.
BTW, I wouldn't use the exact same interface NUnit does:
It is a confusing design
I'd prefer an approach that used generics all the way through
I'd prefer an approach that allowed you to return an IEnumerable<ConstraintViolation> or IEnumerable<string>, rather than taking some sort of output writer class as a dependency
But I'd definitely steal the base concept :)
Implementation
Here's an example implementation of what I'm talking about:
public class ConstraintViolation
{
public ConstraintViolation(IConstraintBase source, string description)
{
Source = source;
Description = description;
}
public IConstraintBase Source { get; }
public string Description { get; set; }
}
public interface IConstraintBase
{
public string Name { get; }
public string Description { get; }
}
public interface IConstraint<T> : IConstraintBase
{
public IEnumerable<ConstraintViolation> GetViolations(T value);
}
And here's an example constraint to validate the length of a string (a weak example, but see my comments about this below):
public class StringLengthConstraint : IConstraint<string>
{
public StringLengthConstraint(int maximumLength)
: this(minimumLength: 0, maximumLength: maximumLength)
{
}
public StringLengthConstraint(int minimumLength, int maximumLength,
bool isNullAllowed = false)
{
MinimumLength = minimumLength;
MaximumLength = maximumLength;
IsNullAllowed = isNullAllowed;
}
public int MinimumLength { get; private set; }
public int MaximumLength { get; private set; }
public bool IsNullAllowed { get; private set; }
public IEnumerable<ConstraintViolation> GetViolations(string value)
{
if (value == null)
{
if (!IsNullAllowed)
{
yield return CreateViolation("Value cannot be null");
}
}
else
{
int length = value.Length;
if (length < MinimumLength)
{
yield return CreateViolation(
"Value is shorter than minimum length {0}",
MinimumLength);
}
if (length > MaximumLength)
{
yield return CreateViolation("Value is longer than maximum length {0}",
MaximumLength);
}
}
}
public string Name
{
get { return "String Length"; }
}
public string Description
{
get
{
return string.Format("Ensure a string is an acceptable length"
+ " - Minimum: {0}"
+ ", Maximum: {1}"
+ "{2}"
, MinimumLength
, MaximumLength
, IsNullAllowed ? "" : ", and is not null"
);
}
}
private ConstraintViolation CreateViolation(string description,
params object[] args)
{
return new ConstraintViolation(this, string.Format(description, args));
}
}
Here's how to use it when doing validation of a single field:
var violations = new StringLengthConstraint(10).GetViolations(value);
if(violations.Any())
{
throw new InvalidArgumentException("value", string.Join(", ", violations));
}
Justification
The string length constraint is a lot of code to do something stupidly simple, especially if you're doing this just once. But there are advantages to this approach:
It is reusable
Write this or use it once, and I'd agree this is a pain.
But most of the code here is to allow this to be reusable. For example you can select this out of a list of constraints for a string type. Or you can display a list of constraints or constraint violations on a UI, with tooltips, etc. Or you can use it in a unit testing framework; With an adapter class it could plug directly into NUnit.
This model supports aggregating constraints and violations
Through Linq
Through object composition
Linq:
var violations = new SomeConstraint(someData).GetViolations(value)
.Concat(new SomeOtherConstraint(someData).GetViolations(value))
;
Object composition:
// ...
public IEnumerable<ConstraintViolation> GetViolations(SomeType value)
{
if(value == 42)
{
yield return new ConstraintViolation(this, "Value cannot be 42");
}
foreach(var subViolation in subConstraint.GetViolations(value))
{
yield return subViolation;
}
}
private SomeSubConstraint subConstraint;

You need to do the following:
Parse your string and figure out (somehow) what type of string it is. I'd prefer to know it before the validation (by assigning types to fields), because if some string is incorrect, you can assign incorrect type for it.
Validate your string based on the validation rules applicable to the given field type. These validators should implement some interface, so you can validate any type of string. Usually you have not only field-type-specific validation, but field-specific-validation, so this kind of validators should also implement the same interface.
Everything else is depending on your app-specific logic.

Related

Comparison of unspecified generic properties

Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}

C# method able to handle/accept different class types

I have a method that accepts a simple class object and builds a URL used in an API call. I would like this method to be able handle/accept different class types that are similar yet have different properties.
public class ClientData
{
public string Name {get; set;}
public string Email {get; set;}
...
}
public class PaymentData
{
public decimal PaymentAmount {get; set;}
public string Description {get; set;}
...
}
Below are two example methods. As you can see they are very similar. Would it better to implement these as different methods accepting different parameters or can one method be written that can deal with parameter object differences?
public string BuildApiCall(ClientData clientDataObject)
{
StringBuilder sb = new StringBuilder();
sb.Append("http://mytestapi.com/");
sb.append("name=" + clientDataObject.Name);
sb.append("email=" + clientDataObject.Email);
return sb.ToString();
}
public string BuildApiCall(PaymentData paymentDataObject)
{
StringBuilder sb = new StringBuilder();
sb.Append("http://mytestapi.com/");
sb.append("payment=" + paymentDataObject.PaymentAmount );
sb.append("description=" + paymentDataObject.Description );
return sb.ToString();
}
Deciding which approach to take
Your problem is, essentially, to create a custom serializer for your classes, based on the provided API (presumably fixed).
To separate concerns as much as possible, this functionality is commonly implemented separately from your entity classes, leaving them (if anyhow possible) as POCOs, or dumb DTOs which are serialization independent, as much as possible. So, just like you would use a XmlSerializer or a DataContractSerializer to serialize a class into XML, or Protobuf.NET to serialize it into protocol buffers, arguably the most general approach would be to create your own serializer.
Of course, as with all other problems you encounter in daily programming, you need to weigh potential benefits and decide how much effort you want to invest into refactoring. If you have a small number of cases, nobody will get hurt by a couple of copy/pasted hard-coded methods, similar to what you're doing now. Also, if this is just a tiny "pet project", then you might decide that you don't want to waste time on potential issues you might encounter while trying to refactor into a more general solution (which you might never need again).
Your goal is to have to write as little as possible
However, if you do choose to invest some time in writing a serializer, then you will quickly note that most serialization frameworks try to rely on convention for serialization as much as possible. In other words, if your class is:
public class ClientData
{
public string Name { get; set; }
public string Email { get; set; }
}
Then a XmlSerializer will, without any configuration at all, produce the following XML:
<ClientData>
<Name>...</Name>
<Email>...</Email>
</ClientData>
It would also be really cool to have a class which would simply spit out ?name=...&email=... for that object, with absolutely no additional work on your side. If that works, than you have a class which will not only remove duplication from existing code, but seriously save time for all future extensions to the API.
So, if you are writing your classes based on the API, then it might make sense to name properties exactly like API members whenever possible (and use convention-based serialization), but still keep it open enough to be able to handle a couple of edge cases separately.
Example code
public class ClientData
{
public string Name {get; set;}
public string Email {get; set;}
}
// customer really insisted that the property is
// named `PaymentAmount` as opposed to simply `Amount`,
// so we'll add a custom attribute here
public class PaymentData
{
[MyApiName("payment")]
public decimal PaymentAmount {get; set;}
public string Description {get; set;}
}
The MyApiName attribute is really simple, just accepts a single string argument:
public class MyApiNameAttribute : Attribute
{
private readonly string _name;
public string Name
{ get { return _name; } }
public MyApiNameAttribute(string name)
{ _name = name; }
}
With that in place, we can now use a bit of reflection to render the query:
public static string Serialize(object obj)
{
var sb = new StringBuilder();
foreach (var p in obj.GetType().GetProperties())
{
// default key name is the lowercase property name
var key = p.Name.ToLowerInvariant();
// we need to UrlEncode all values passed to an url
var value = Uri.EscapeDataString(p.GetValue(obj, null).ToString());
// if custom attribute is specified, use that value instead
var attr = p
.GetCustomAttributes(typeof(MyApiNameAttribute), false)
.FirstOrDefault() as MyApiNameAttribute;
if (attr != null)
key = attr.Name;
sb.AppendFormat(
System.Globalization.CultureInfo.InvariantCulture,
"{0}={1}&",
key, value);
}
// trim trailing ampersand
if (sb.Length > 0 && sb[sb.Length - 1] == '&')
sb.Length--;
return sb.ToString();
}
Usage:
var payment = new PaymentData()
{
Description = "some stuff",
PaymentAmount = 50.0m
};
// this will produce "payment=50.0&description=some%20stuff"
var query = MyApiSerializer.Serialize(payment)
Performance
As noted in the comments, the power of reflection does incur a performance penalty. In most cases, this should not be of much concern. In this case, if you compare the cost of building the query string (probably in the range of 10s of microseconds) with the cost of executing the HTTP request, you'll see that it's pretty much negligible.
If, however, you decide that you want to optimize, you can easily do it at the end, after profiling, by changing that single method which does all the work by caching property information or even compiling delegates. That's good about separation of concerns; duplicated code is hard to optimize.
Define an interface:
public interface IWhatsit
{
string ToApiString();
}
Now have your data objects implement it. ToApiString should return the query string part for this particular object:
public class ClientData : IWhatsit
{
public string Name {get; set;}
public string Email {get; set;}
...
public string ToApiString()
{
// Do whatever you need here - use a string builder if you want
return string.Format("Name={0}&Email={1}",Name,Email);
}
}
And now you can have a single method for making the API call:
public string BuildApiCall(IWhatsit thing)
{
StringBuilder sb = new StringBuilder();
sb.Append("http://mytestapi.com/");
sb.append(thing.ToApiString());
return sb.ToString();
}
Note: You could use a property instead of a method in the interface if you so wished.
An alternative approach would be to use an abstract base class and inherit from that. Then you could do something like this:
public abstract class BaseData
{
protected abstract string ToApiString();
public string BuildApiCall()
{
StringBuilder sb = new StringBuilder();
sb.Append("http://mytestapi.com/");
sb.append(ToApiString());
return sb.ToString();
}
}
And then each class would look something like this:
public class ClientData : BaseData
{
public string Name {get; set;}
public string Email {get; set;}
...
protected override string ToApiString()
{
// Do whatever you need here - use a string builder if you want
return string.Format("Name={0}&Email={1}",Name,Email);
}
}
Which lets you put BuildApiCall inside the class itself and have a base implementation. Of course, if you do need BuildApiCall to be outside of these classes, then you could do that. It would just take a BaseData and you'd have to make ToApiString public rather than protected.

`Type.GetProperties` property order

Short Version
The MSDN documentation for Type.GetProperties states that the collection it returns is not guaranteed to be in alphabetical or declaration order, though running a simple test shows that in general it is returned in declaration order. Are there specific scenarios that you know of where this is not the case? Beyond that, what is the suggested alternative?
Detailed Version
I realize the MSDN documentation for Type.GetProperties states:
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
so there is no guarantee that the collection returned by the method will be ordered any specific way. Based on some tests, I've found to the contrary that the properties returned appear in the order they're defined in the type.
Example:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Simple Properties:
FieldB
FieldA
FieldC
One such case that this differs only slightly is when the type in question has a parent who also has properties:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC
Which means the GetProperties method walks up the inheritance chain from bottom up when discovering the properties. That's fine and can be handled as such.
Questions:
Are there specific situations where the described behavior would differ that I've missed?
If depending on the order is not recommended then what is the recommended approach?
One seemingly obvious solution would be to define a custom attribute which indicates the order in which the properties should appear (Similar to the Order property on the DataMember attribute). Something like:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}
And then implement such as:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}
But as many have found, this becomes a serious maintenance problem if your type has 100 properties and you need to add one between the first 2.
UPDATE
The examples shown here are simply for demonstrative purposes. In my specific scenario, I define a message format using a class, then iterate through the properties of the class and grab their attributes to see how a specific field in the message should be demarshaled. The order of the fields in the message is significant so the order of the properties in my class needs to be significant.
It works currently by just iterating over the return collection from GetProperties, but since the documentation states it is not recommended I was looking to understand why and what other option do I have?
The order simply isn't guaranteed; whatever happens.... Happens.
Obvious cases where it could change:
anything that implements ICustomTypeDescriptor
anything with a TypeDescriptionProvider
But a more subtle case: partial classes. If a class is split over multiple files, the order of their usage is not defined at all. See Is the "textual order" across partial classes formally defined?
Of course, it isn't defined even for a single (non-partial) definition ;p
But imagine
File 1
partial class Foo {
public int A {get;set;}
}
File 2
partial class Foo {
public int B {get;set:}
}
There is no formal declaration order here between A and B. See the linked post to see how it tends to happen, though.
Re your edit; the best approach there is to specify the marshal info separately; a common approach would be to use a custom attribute that takes a numeric order, and decorate the members with that. You can then order based on this number. protobuf-net does something very similar, and frankly I'd suggest using an existing serialization library here:
[ProtoMember(n)]
public int Foo {get;set;}
Where "n" is an integer. In the case of protobuf-net specifically, there is also an API to specify these numbers separately, which is useful when the type is not under your direct control.
For what it's worth, sorting by MetadataToken seemed to work for me.
GetType().GetProperties().OrderBy(x => x.MetadataToken)
Original Article (broken link, just listed here for attribution):
http://www.sebastienmahe.com/v3/seb.blog/2010/03/08/c-reflection-getproperties-kept-in-declaration-order/
I use custom attributes to add the necessary metadata myself (it's used with a REST like service which consumes and returns CRLF delimited Key=Value pairs.
First, a custom attribute:
class ParameterOrderAttribute : Attribute
{
public int Order { get; private set; }
public ParameterOrderAttribute(int order)
{
Order = order;
}
}
Then, decorate your classes:
class Response : Message
{
[ParameterOrder(0)]
public int Code { get; set; }
}
class RegionsResponse : Response
{
[ParameterOrder(1)]
public string Regions { get; set; }
}
class HousesResponse : Response
{
public string Houses { get; set; }
}
A handy method for converting a PropertyInfo into a sortable int:
private int PropertyOrder(PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
Even better, write is as an extension:
static class PropertyInfoExtensions
{
private static int PropertyOrder(this PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
}
Finally you can now query your Type object with:
var props = from p in type.GetProperties()
where p.CanWrite
orderby p.PropertyOrder() ascending
select p;
Relying on an implementation detail that is explicitly documented as being not guaranteed is a recipe for disaster.
The 'recommended approach' would vary depending on what you want to do with these properties once you have them. Just displaying them on the screen? MSDN docs group by member type (property, field, function) and then alphabetize within the groups.
If your message format relies on the order of the fields, then you'd need to either:
Specify the expected order in some sort of message definition. Google protocol buffers works this way if I recall- the message definition is compiled in that case from a .proto file into a code file for use in whatever language you happen to be working with.
Rely on an order that can be independently generated, e.g. alphabetical order.
1:
I've spent the last day troubleshooting a problem in an MVC 3 project, and it all came down to this particular problem. It basically relied on the property order being the same throughout the session, but on some occations a few of the properties switched places, messing up the site.
First the code called Type.GetProperties() to define column names in a dynamic jqGrid table, something that in this case occurs once per page_load. Subsequent times the Type.GetProperties() method was called was to populate the actual data for the table, and in some rare instances the properties switched places and messed up the presentation completely. In some instances other properties that the site relied upon for a hierarchical subgrid got switched, i.e. you could no longer see the sub data because the ID column contained erroneous data. In other words: yes, this can definitely happen. Beware.
2:
If you need consistent order throughout the system session but not nessecarily exactly the same order for all sessions the workaround is dead simple: store the PropertyInfo[] array you get from Type.GetProperties() as a value in the webcache or in a dictionary with the type (or typename) as the cache/dictionary key. Subsequently, whenever you're about to do a Type.GetProperties(), instead substitute it for HttpRuntime.Cache.Get(Type/Typename) or Dictionary.TryGetValue(Type/Typename, out PropertyInfo[]). In this way you'll be guaranteed to always get the order you encountered the first time.
If you always need the same order (i.e. for all system sessions) I suggest you combine the above approach with some type of configuration mechanism, i.e. specify the order in the web.config/app.config, sort the PropertyInfo[] array you get from Type.GetProperties() according to the specified order, and then store it in cache/static dictionary.

Designing a Requirement Satisfaction structure

I'm attempting to implement a 'Requirements' type system into a program. It seemed pretty simple in my head, but actually making it abstract enough to be useful is proving more difficult than anticipated.
Here is what I am trying to do ...
enum Condition {
Not, Exists, Exceeds
}
abstract class Requirement {
// base class
Condition Condition { get; set; }
}
class ScoreRequirement : Requirement {
// a specific 'score' is required
}
class TraitRequirement : Requirement {
// a specific 'trait' is required
}
class SatisfyingObject {
// this is the class that has to satisfy the requirements
IDictionary<Trait, int> Traits { get; set; }
}
If I know the exact thing that has to be satisfied in code-time, this is very simple. But the goal is to let people add requirements later. There will be other types that derive from Requirement, as well.
So a requirement might work like this ...
var obj = new Item {
Requirements = new List<Requirement> {
new ScoreRequirement { Trait = "One", Score = 2, Condition = Condition.Exceeds }
}
}
So the concept seems pretty simple. You would call upon an object..
var satisfying = // get the satisfying object;
if( satisfying.Satisfies( obj.Requirements ) )
return true;
The problem I am running into is really how to code the Satisfies method - in specific I am not sure how to relate it to the Condition parameter. I'd like people to be able to set up some fairly generic 'requirements', but the logic behind this is very confusing to me. Since the requirements are not known at design time, I cannot really hard code any of them.
Any suggestions?
If this isn't a learning project than I would highly recommend you look at using something that is already built for this:
EntLib Validation Block
Fluent Validation
Anything built on top of the System.ComponentModel.DataAnnotations
If however you are doing this as a simple learning project, than you have 2 basic approaches you could take:
Reflection based
Delegate based
Of the two, delegate based is going to be much simpler to implement, but less flexible. I have implemented this pattern several times and the concept is simple. Here is about the most basic concept you can get.
public interface IRuleDefinition
{
String PropertyName { get; }
String Message { get; }
}
public class ValidationRule<T>: IRuleDefinition
{
public String PropertyName { get; private set; }
public String Message { get; private set; }
private Func<T, Boolean> _isValidDelegate;
public ValidationRule(Func<T, Boolean> isValidDelegate, String propertyName, String message)
{
PropertyName = propertyName;
Message = message;
_isValidDelegate = isValidDelegate;
}
public Boolean IsValid(T objToValidate)
{
return _isValidDelegate(objToValidate);
}
}
public class Validator<T>
{
private List<ValidationRule<T>> _validationRules = new List<ValidationRule<T>>();
public void AddRule(Func<T, Boolean> isValidDelegate, String propertyName = null, String message = null)
{
_validationRules.Add(new ValidationRule<T>(isValidDelegate, propertyName, message));
}
public Boolean IsValid(T objToValidate)
{
return _validationRules.Any(vr => vr.IsValid(objToValidate));
}
public IEnumerable<IRuleDefinition> GetViolations(T objToValidate)
{
return _validationRules
.Where(vr => !vr.IsValid(objToValidate))
.Cast<IRuleDefinition>();
}
}
You can use it in code like this:
var myObj = new MyObject{ Name = "Josh", Age = 29 };
var myObjValidator = new Validator<MyObject>();
myObjValidator.AddRule(
obj => !String.IsNullOrWhitespace(obj.Name),
"Name", "Name is required!");
myObjValidator.AddRule(
obj => obj.Age < 99,
"Age", "Age must be less than 99");
myObjValidator.AddRule(
obj => obj.Name == "Logan" && obj.Age < 29,
message: "RUN!!!");
if(!myObjValidator.IsValid(myObj))
{
foreach(var violation in myObjValidator.GetViolations(myObj))
Console.WriteLine("Property: {0}, Message: {1}",
violation.PropertyName, violation.Message);
}
Now, this was all from memory, so there may be some are probably coding/compiler errors in all this, but hopefully you get the general idea.
Again, if this isn't a learning project, then don't reinvent the wheel unless you are planning to learn more about wheels :)
I recommend determining the bare minimum scope required for specifying requirements and start with that, to see how complex the design becomes. If you're finding that even the minimum scope leads to a lot of complexity or if you can't even get a grasp on what the minimum scope would be, then you may want to look into a more flexible approach, like hosting a scripting language to be used for expressing your constraints. There are a wide range of available libraries to support this and they will be cheaper to support/maintain than something you've created and evolved yourself in an effort to provide an 'easy' way of setting constraints.
Keep it simple if you can, but if it really does need to be complicated, try to find something already built and tested as a foundation, so as to reduce the burden of the complexity.

Which design option is more suitable for auto-correction on construction?

Trying to decipher an appropriate OO design to implement. The basic scenario is that you have a PstnNumber which is essentially a 10 digit phone number that always starts with 0 (e.g. 0195550000). A rule has been introduced to allow auto-correcting of a number if the leading 0 is missing (e.g. 195550000).
START EDIT
I realised the original question may have been misunderstood (thankyou kindly to those whom have answered already), so I have edited to try and better explain the scenario.
END EDIT
I started playing with some preliminary concepts and then thought I would ask if there was a more appropriate way to go or do one of these suffice (on some level)?
Concept 1
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number)
{
this.Number = number;
}
}
public class AutoFormattedPstnNumber : PstnNumber
{
public override string Number
{
get { return base.Number; }
set { base.Number = value.PadLeft(10, '0'); }
}
public AutoFormattedPstnNumber() : base() { }
public AutoFormattedPstnNumber(string number)
{
this.Number = number;
}
}
Concept 2 (removed)
Concept 3
public class PstnNumber
{
public bool AutoCorrect { get; set; }
private string number;
public virtual string Number
{
get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; }
set { this.number = value; }
}
public PstnNumber() : this(false) { }
public PstnNumber(bool autoCorrect)
{
this.AutoCorrect = autoCorrect;
}
public PstnNumber(string number) : this(false)
{
this.Number = number;
}
public PstnNumber(string number, bool autoCorrect) : this(autoCorrect)
{
this.Number = number;
}
}
I think Concept 1 may violate the Liskov Substitution rule because the subclass changes the behaviour of the Number property (happy to learn if I've misunderstood that).
Any alternative suggestions would be received happily.
do you have to do the autoformatting when the object is instantiated? If not,
what about:
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number) { this.Number = number; }
public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } }
}
avoid getter-setter-surprise
Avoid getters returning a different value than the one accepted by the setter. Imagine the following snippet:
if (input.Value != current.Number)
{
NumberChangedAgain = true;
current.Number = input.Value;
}
A simple solution would be to make PstnNumber immutable:
temp = PstnNumber.FromString(input.Value);
if (temp != current) { ... }
canonical format
If some data has different representations, there is a lot of advantage to storing it in a canonical representation, and move the format conversions to factory functions and getters / formatters. For example, you don't need to test comparison for short vs. long, long vs. short, short vs. short, long vs. long.
different aspects
Do you need the distinction between an "autoformatted" and a "normal" number, or is this merely a question of input and output - i.e.
does display format (short or long) depend on how the number was entered, or on where it is displayed?
is 0195550000 == 195550000 ?
I'd prefer to fold both classes into one if possible (i.e. when "entered with or without 0 can be forgotten"):
public class PstnNumber
{
private string m_number; // always in long format
public static PstnNumber(string s) { ... } // accepts short and long form
public string Number { get { return m_number; } }
public string AutoFormatted { { get { ... } }
}
Otherwise I'd go with Option 3, but always store the long format in m_number.
In Option 1 and Option 2, you aren't preserving the original number anyway, rendering the subclass worthless (except to know that it was autoformatted at some point, which doesn't seem like useful information). The alternative to make these Options more useful would be to format on Get instead of Set.
Option 3 is therefore the preferred pattern out of these three options, but I would also ask - why can't the PstnNumber also simply detect the number of digits, and autoformat accordingly?
If you follow the rules - there is one that says that "each routine (read class) should do only one thing and do it well".
According to that I would make PstnNumber just hold the number, and create some sort of factory that produces the right number.
Doing both in the same class means that you are weaving domain logic and representation. I prefer them separated.
I'd ask why your class name is so cryptic. "Number" is clear to me, and "P" suggests "phone", but what's the "stn" telling me? A few extra keystrokes would make this class more self-documenting.
I'd also ask about the logic of a default constructor that does not initialize the underlying data members to some value. I think a default constructor should have a sensible default value if possible.
I feel like option 1 is overkill. I don't think inheritance is making this model clearer or better. I don't see how it breaks Liskov substitution, which demands that you can use the subclass in any situation that calls for a base class. The methods map 1:1 as far as I can see. How is Liskov violated?
Option 2 says these are two separate classes with no relationship. That doesn't seem right to me.
All this work suggests that your problem will require that you use both classes. You'll have situations where the leading zero is NOT required and others where it is. Is that true? Or are you always going to require the leading zero?
I don't care for any of your options. I'd prefer an interface or a static factory or even modifying the class you have to anything you've suggested. It feels like a mere formatting issue. Do you store the number with the leading zero? If not, maybe it's just a view concern.
Do you have a really strong reason to have a setter and not have your members final? If not, that's probably a bigger problem than any other variation between the three.
So I'd go for a stateless #3 which means making the number final and gettng rid of the autoFormat variable.
For simplicity I'd just have a getNumberRaw and getNumberFormatted
Better yet, you could have getNumberRaw and getNumber(formatType) where formatType actually contains the code that formats the number since the format may change again in the future and combining formatting (view) with your phone number (model) isn't optimal.
(PS/EDIT): just the fact that a phone number can change is NOT a good reason to have a setter! Creating a new phone number object and replacing the old one will almost always work!
I am not familiar with c#, but I'd do this:
public class PstnNumber {
readonly string number;
public PstnNumber(string number) {
this.number = number;
}
public string getNumber() {
return number;
}
static public PstnNumber createNumber(string number) {
return new PstnNumber(number.PadLeft(10, '0'));
}
}
Of course if I knew how Properties work, I'd probably do it differently :)
I would go with a much simpler version, overriding the ToString method, or even, creating an ToString overload that receives the bool parameter indicating that the number should be formatted.

Categories

Resources