I am building a simple Guard API to protect against illegal parameters being passed to functions and so on.
I have the following code:
public static class Guard
{
public static GuardArgument<T> Ensure<T>(T value, string argumentName)
{
return new GuardArgument<T>(value, argumentName);
}
}
public class GuardArgument<T>
{
public GuardArgument(T value, string argumentName)
{
Value = value;
Name = Name;
}
public T Value { get; private set; }
public string Name { get; private set; }
}
// Example extension for validity checks
public static GuardArgument<T> IsNotNull<T>(this GuardArgument<T> guardArgument, string errorMessage)
{
if (guardArgument.Value == null)
{
throw new ArgumentNullException(guardArgument.Name, errorMessage);
}
return guardArgument;
}
At the moment the code can be used in a similar way to (note this is just a dumb example):
void DummyMethod(int? someObject) {
Guard.Ensure(someObject, "someObject")
.IsNotNull()
.IsGreaterThan(0)
.IsLessThan(10);
}
This all works fine. What I want to be able to do now is extend the API to include child properties in the checks in the following way:
Guard.Ensure(someObject, "someObject")
.IsNotNull()
.Property(
(x => x.ChildProp1, "childProp1")
.IsNotNull()
.IsGreaterThan(10)
)
.Property(
(x => x.ChildProp2, "childProp2")
.IsNotNull()
.IsLessThan(10)
);
Obviously the new .Property method needs to return the parent GuardArgument in order to chain. Furthermore the child property needs to be able to use the existing check methods (IsNotNull() etc) to avoid code duplication.
I cannot work out how to construct the lambda/Property function parameters or where the .Property method should be located - i.e. should it be a property on the GuardArgument or somewhere else, or even if there is a better structure to the API.
The following function allows for a similar syntax to what you want.
public static GuardArgument<T> Property<T, TProp>(this GuardArgument<T> guardArgument, Func<T, TProp> getProperty, string propertyName, Action<GuardArgument<TProp>> validate)
{
GuardArgument<TProp> propertyGuardArgument = new GuardArgument<TProp>(getProperty(guardArgument.Value), propertyName);
validate(propertyGuardArgument);
return guardArgument;
}
The function creates a new GuardArgument for the selected property and then passes this into the Action parameter to allow you to validate as you wish.
This also allows infinite chaining of properties, although I'm not sure that would be particularly readable.
Usage:
Guard.Ensure(someObject, "someObject")
.IsNotNull()
.Property(x => x.ChildProp1, "childProp1", childProp1 =>
childProp1.IsNotNull()
.IsLessThan(10)
.Property(y => y.InnerChildProperty, "innerChildProperty", innerChildProperty =>
innerChildProperty.IsNotNull()
)
)
.Property(x => x.ChildProp2, "childProp2", childProp2 =>
childProp2.IsNotNull()
.IsGreaterThan(10)
);
I think you have no benefit from putting the property checks in the chain of the parent object checks. So I would recommend to make one chain for the parent object and for each property another chain. This is much more readable:
Guard.Ensure(a, "a")
.IsNotNull("a is null");
Guard.Ensure(a.p0, "a.p0")
.IsGreaterThan(10);
Guard.Ensure(a.p1, "a.p1")
.IsGreaterThan(5);
I think you are reinventing a wheel here. Install this extension - Code Contracts and here is docs how to use it.
In addition to code based asserts similar to yours, i.e. :
public int[] Bar(){
Contract.Ensures( Contract.ForAll(0, Contract.Result<int[]>().Length, index => Contract.Result<int[]>()[index] > 0));
....
}
or
Contract.Requires<ArgumentNullException>( x.Value.NestedObject != null, ”x.Value.NestedObject” );
But also has attributes and extensive set of functions for checking interfaces, nice pre- and post- conditions etc. check it out!
Related
I want to make this code shorter, via passing the type as a parameter to targetUnitOfWork.Query.
There are two types SomeListItem and SomeList. And depending on the actual type I have to call either Query<SomeListItem> or Query<SomeList> as it is shown below.
Type typeName = targetClassInfo.ClassType;
if (typeName.Equals(typeof(SomeListItem)))
{
target = targetUnitOfWork
.Query<SomeListITem>()
.Where(i => i.Name.Equals(otherObj.Name)).Where(j => j.SortKey == otherObj.SortKey);
}
else if (typeName.Equals(typeof(SomeList)))
{
target = targetUnitOfWork
.Query<SomeList>()
.Where(i => i.Name.Equals(otherObj.Name)).Where(j => j.SortKey == otherObj.SortKey);
}
else
{
target = targetClassInfo.CreateNewObject(targetUnitOfWork);
}
How can I solve this task?
Preface
We will not cover in this answer the design decision made by the authors of the code. It's only worth to say that this kind of heterogeneous generics should be left to pattern matching mechanism instead of polymorphic one.
Motivation
Either way, there are plenty of cases where you want to dynamically put generic types and invoke methods in the chain. It's mostly done in projects serving libraries and frameworks for later usage, where parameters are inherited from the user input, or they come lately to the project as an extension by the developers.
Reflection
Luckily, .NET Framework (and Core as well, the code bellow is .NET Framework) provides a rich Reflection library where you can do your metaprogramming model.
The Reflection library provides a way to introspect the program, compromising the static typization in favor of dynamic one e.g. to find a method by its name, because it comes from the user input. It's not its sole purpose, but we will use it this way.
Action in code
In our scenario, we need to call the Query<T> method with arbitrary <T> which comes from the user input. So let's define a function that will serve this functionality. We will call it Test:
static void Test(Type type, TestGenerics testGenerics, String otherObjectName)
It receives the System.Type, an object in our case TestGenerics and a String to test the name property as in the question.
Our TestGenerics object is a fake class that mimics the question's semantics:
class TestGenerics
{
public IEnumerable<T> Query<T>() where T : new()
{
return Enumerable.Repeat(new T(), 10);
}
}
First of all, we need to find the Query method by name. Since it's the one and only method named this way (no overloads) we can safely use FirstOrDefault:
Object enumerable = testGenerics.GetType().GetMethods().FirstOrDefault(m => m.Name == "Query")
But we cannot invoke it directly, as it accepts not only arguments, but generic parameters as well. We can provide them, by providing Type to MakeGenericMethod(Type) reflection's method:
.MakeGenericMethod(type)
And then we are ready to Invoke it without arguments (as it does not accept any), but we need to specify the object it will be invoked from (in our case testGenerics):
.Invoke(testGenerics, null);
Cool so far, there are the dragons to come here, because we need now to build the i => i.name == otherObjectName lambda. The Where method from IEnumerable<T> extensions (in fact, it's a static method in System.Linq.Enumerable) receives a Func<T, R> instead of Predicate<T>, so we need to build one:
Type predicateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
This builds Func<,> e.g. a Func type with two generic parameters. The first is the type passed, and the second is boolean to mimic a predicate by function.
Now we need to build the lambdas left side by making a parameter of the given type:
ParameterExpression predParam = Expression.Parameter(type, "i");
And getting the field name from it them:
Expression left = Expression.Field(predParam, type.GetField("name"));
And the right side of the expressions is the name we will compare it with:
Expression right = Expression.Constant(otherObjectName, typeof(string));
Building the whole lambda is the next step. From the predicate type (Func<T, R>, the equality expression and the predicate param "i"):
LambdaExpression lambda = Expression.Lambda(predicateType, Expression.Equal(left, right), predParam);
Now we need to find the Where method. It's in the class containing all the extension methods and not in the IEnumerable interface:
IEnumerable<MethodInfo> methodsEnumerable = typeof(System.Linq.Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public);
MethodInfo where = methodsEnumerable.Where(m => m.GetParameters().Length == 2).FirstOrDefault(m => m.Name == "Where");
But this is a generic method, receiving the type from the input, so we need to do this as well:
MethodInfo genericWhere = where.MakeGenericMethod(type);
Since it is a static method, the object must be passed as an argument (as for the semantics of an extension method). The first argument in the object array is the extension interface (IEnumerable e.g. the return type of Query) and the second argument is the above lambda - compiled:
Object response = genericWhere.Invoke(enumerable, new[] {enumerable, lambda.Compile()});
And here we will stop with the example. You will need to tweak it for your case and add the other method calls. It's very verbose and ugly as well, but will work for any kind of objects containing the name field. In bigger scenarios, if you don't couple to a certain field hardcoded, it will work for wide variety of inputs. The same way how frameworks works with our code.
The full example you can find below:
class TypeOne
{
public string name;
}
class TypeTwo
{
public string name;
}
internal class Program
{
public static void Main(string[] args)
{
Test(typeof(TypeOne), new TestGenerics(), "John");
Test(typeof(TypeTwo), new TestGenerics(), "Smith");
}
static void Test(Type type, TestGenerics testGenerics, String otherObjectName)
{
Object enumerable = testGenerics.GetType().GetMethods().FirstOrDefault(m => m.Name == "Query")
.MakeGenericMethod(type)
.Invoke(testGenerics, null);
Type predicateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
ParameterExpression predParam = Expression.Parameter(type, "i");
Expression left = Expression.Field(predParam, type.GetField("name"));
Expression right = Expression.Constant(otherObjectName, typeof(string));
LambdaExpression lambda = Expression.Lambda(predicateType, Expression.Equal(left, right), predParam);
IEnumerable<MethodInfo> methodsEnumerable = typeof(System.Linq.Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public);
MethodInfo where = methodsEnumerable.Where(m => m.GetParameters().Length == 2).FirstOrDefault(m => m.Name == "Where");
MethodInfo genericWhere = where.MakeGenericMethod(type);
Object response = genericWhere.Invoke(enumerable, new[] {enumerable, lambda.Compile()});
Console.WriteLine(response);
}
}
class TestGenerics
{
public IEnumerable<T> Query<T>() where T : new()
{
return Enumerable.Repeat(new T(), 10);
}
}
Why don't use generic method like this:
private void SomeMethod<T>()
{
target = targetUnitOfWork
.Query<T>()
.Where(i => i.Name.Equals(otherObj.Name)).Where(j => j.SortKey == otherObj.SortKey);
}
Then you can call SomeMethod<SomeList>() or SomeMethod<SomeListItem>()
This is what you want to do, right?
class Program
{
static void Main(string[] args)
{
List<object> listOfObjects = new List<object>() { new Item(), new Dog(), new Cat(), new Human() };
Dog martin = GetFirstOrDefault<Dog>(listOfObjects);
}
static T GetFirstOrDefault<T>(List<object> listOfObjects)
{
return (T)listOfObjects.Where(x => x.GetType() == typeof(T)).FirstOrDefault();
}
}
class Item
{
public string Name { get; set; }
public string Color { get; set; }
}
class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
class Cat
{
public string Name { get; set; }
public int Age { get; set; }
}
class Human
{
public string Name { get; set; }
public DateTime Birth { get; set; }
}
Things are only going to get complicated (messy?) from here on.
Ok, so first two queries are same. So, you might go for a generic method. Something of this sort:
public IEnumerable<T> GetListTarget<T>(bool applyWhere) // You will need to add an constraint here that is applicable to both classes. Only then compiler will be able to understand the properties you are using in the where method
{
if (applyWhere)
{
return targetUnitOfWork
.Query<T>()
.Where(i => i.Name.Equals(otherObj.Name)).Where(j => j.SortKey == otherObj.SortKey);
}
else
{
return targetClassInfo.CreateNewObject(targetUnitOfWork);
}
}
I'm trying to find a good design to a thing I'm working on. As an example, consider a TextProcessor class that accepts a string parameter and returns back a processed string.
Now in my implementation there are a number of different TextProcessors, each capable handling their own defined set of strings. There are two notable methods in each processor:
bool CanProcess(string text);
and
string Process(string text);
In reality these can be marked as static but for the sake of implementing a common interface I'm not setting them as static.
In addition to these TextProcessors there is a static TextProcessorFinder class. As the name implies, it finds the best TextProcessor and processes the input.
public static class TextProcessorFinder
{
private static List<ITextProcessor> _processors;
static TextProcessorFinder()
{
_processors = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.GetInterfaces().Contains(typeof(ITextProcessor))
&& t.IsClass && !t.IsAbstract)
.Select(t => (ITextProcessor)Activator.CreateInstance(t))
.Where(t => t.IsActive)
.ToList();
}
public static ITextProcessor GetTextProcessor(string text)
{
return _processors.Where(p => p.CanProcess(text))
.OrderByDescending(p => p.Priority)
.FirstOrDefault();
}
}
What I hate about this approach is that I have to create an instance of every known TextProcessor just to call their CanProcess function.
I have tried creating an attribute with a simple Func to emulate the CanProcess function:
[AttributeUsage(AttributeTargets.Class)]
public class TextProcessorAttribute : Attribute
{
private Func<string, bool> func;
public TextProcessorAttribute(Func<string, bool> func)
{
this.func = func;
}
}
public interface ITextProcessor
{
bool IsActive { get; }
int Priority { get; }
bool CanProcess(string text);
string Process(string text);
}
// Hard-coded to true
[TextProcessor((s) => { return true; })]
public class SampleTextProcessor : ITextProcessor
{
// Implement ITextProcessor
}
Sadly however, Func is not a valid attribute parameter type.
What is the best way of doing this?
In my opinion, creating those instances is the best way to go. There really is no reason to not do it. Instances are cheap and creating them is cheap as well if you are not doing any work in the constructors - which you shouldn't do anyway.
With the CanProcess method you ask to each derived ITextProcessor if he can process the text. This is OK in my opinion.
Maybe there are some sort of specialization in the implementations of ITextProcessor, in this case you can create more specific interfaces, ITextTypeAProcessor, ITextTypeBProcessor, etc. Then you can filter by interface in your GetTextProcessor method.
Let's assume that I have these dummy classes defined:
public class MyObject
{
public InterestingFact InterestingFact { get; set; }
}
public class InterestingFact
{
public Detail Detail { get; set; }
}
public class Detail
{
public string Information { get; set; }
}
I also have an instance of MyObject:
var obj = new MyObject() { InterestingFact = new InterestingFact() };
If I want to try to access the Information property, I could do something like this:
string info = null;
if (obj != null
&& obj.InterestingFact != null
&& obj.InterestingFact.Detail != null)
{
info = obj.InterestingFact.Detail.Information;
}
Ignoring, for the sake of this discussion, the Law of Demeter, this is not a whole lot of fun every time I want to access something deep within an object I have. I can, of course, create an extension method:
public static U NullOr<T, U>(this T target, Func<T, U> selector)
{
if (EqualityComparer<T>.Default.Equals(target, default(T)))
{
return default(U);
}
return selector(target);
}
This makes selecting the data a little easier:
// Here I have a null of type string.
var info = obj.NullOr(o => o.InterestingFact).NullOr(f => f.Detail).NullOr(d => d.Information);
However, this is still a little long winded. Ideally, I'd like to do something more like this:
// Here I should still have a null of type string.
var info = obj.NullOr(o => o.InterestingFact.Detail.Information);
I've never worked with Expressions; if I take in an Expression<Func<T, U>> instead of the Func<T, U> in NullOr, it looks to me like it is one member access rather than three. Is there a way to approach the above, or is this formulation out of reach?
(There's also, of course, the concern with the last fomulation that the expression sent in could be something other than just chained member access..)
About the simplest way you can achieve the desired result with an extension method is the following.
public static class ExtensionMethods
{
public static TR DefaultIfNull<T, TR>(this T source, Expression<Func<T, TR>> expr, TR defaultValue = default(TR))
{
TR result = defaultValue;
try
{
result = expr.Compile().Invoke(source);
}
catch (NullReferenceException)
{
// DO NOTHING
}
return result;
}
}
And here is some example usages of the above
var info1 = obj.DefaultIfNull(x => x.InterestingFact.ToString(), "Null1");
var info2 = obj.DefaultIfNull(x => x.InterestingFact.Detail.ToString(), "Null2");
var info3 = obj.DefaultIfNull(x => x.InterestingFact.Detail.Information);
Note that this is not the BEST solution as it doesn't check individual expression nodes for null, so if any node in the tree happens to internally generate an NullReferenceException then the default value would be returned instead of the exception being thrown. However, for general and simple usage this is probably the optimal solution (mostly for its simplicity).
Is it possible to check the value of a parameter natively using an attribute? I have seen some system attributes like [FromUri] used this way. I'm hoping for something like this:
public void Method([NotNull] string name, [NotNull] DateTime? date)
{ }
where NotNull is an attribute that checks the value to see if it is null. If the value is null it will throw an error.
Here is what I currently have
I'm currently using a static helper class that takes an expression and the parameter itself to determine whether the value is null and uses the expression to determine the name of the parameter.
// Invoke method within ArgumentHelper class
ArgumentHelper.RequireNotNullOrEmpty(() => state, state);
// Method within static class ArgumentHelper
public static void RequireNotNullOrEmpty<T>(this Expression<Func<T>> argumentExpression, string value)
{
var body = ((MemberExpression)argumentExpression.Body);
if (string.IsNullOrEmpty(value))
{
// Throw error "Required field '" + body.Member.Name + "' is missing.";
}
}
Bonus: It would also be nice if I could somehow get the name of the variable without passing a string with its name, just like my current solution.
Definitely not the most performant, but you're on the right track. Here's a wrapper that does a little of what PostSharp would be doing in IL. This is only good for passing objects, it breaks down as is when passing another method as a parameter. However, fixing that problem is just a little more work.
In production I would expand this to build the reflection into a delegate that I could cache for later use.
public class SomeClass
{
public void Method([NotNull] string Param1, [NotNull] string Param2)
{ }
}
public static class SomeClassExtensions
{
public static void InvokeWithNullCheck<TObject>(this TObject obj, Expression<Action<TObject>> expression)
{
var body = (MethodCallExpression)expression.Body;
foreach(var parameter in body.Method.GetParameters())
{
bool hasNotNullAttribute = parameter.CustomAttributes.Any(x => x.AttributeType.Equals(typeof(NotNullAttribute)));
if(hasNotNullAttribute && ((ConstantExpression)body.Arguments[parameter.Position]).Value == null)
{
throw new ArgumentException(String.Format("Mandatory parameter {0} was not supplied.", parameter.Name));
}
}
expression.Compile()(obj);
}
}
[TestFixture]
public class SomeClassTests
{
[Test]
public void Test()
{
var test = new SomeClass();
Assert.Throws<ArgumentException>(() => test.InvokeWithNullCheck(x => x.Method(null, "Test")));
}
}
Take a look at PostSharp (see: http://www.postsharp.net). It provides a lot of attributes like that one you are looking for.
PostSharp is a precompiler which will lookup the attributes in your code and generate appropriate code like parameter validation.
I'm looking to create an ValidationRule class that validates properties on an entity type object. I'd really like to set the name of the property to inspect, and then give the class a delegate or a lambda expression that will be evaluated at runtime when the object runs its IsValid() method. Does anyone have a snippet of something like this, or any ideas on how to pass an anonymous method as an argument or property?
Also, I'm not sure if I'm explaining what I'm trying to accomplish so please ask questions if I'm not being clear.
Really, what you want to use is Func<T,bool> where T is the type of the item you want to validate. Then you would do something like this
validator.AddValidation(item => (item.HasEnoughInformation() || item.IsEmpty());
you could store them in a List<Func<T,bool>>.
class ValidationRule {
public delegate bool Validator();
private Validator _v;
public ValidationRule(Validator v) { _v = v; }
public Validator Validator {
get { return _v; }
set { _v = value; }
}
public bool IsValid { get { return _v(); } }
}
var alwaysPasses = new ValidationRule(() => true);
var alwaysFails = new ValidationRule(() => false);
var textBoxHasText = new ValidationRule(() => textBox1.Text.Length > 0);
That should get you started. But, really, inheritance is far more appropriate here. The problem is simply that the Validator doesn't have access to any state that it doesn't close over, this means that it isn't as reusable as say ValidationRules that contain their own state. Compare the following class to the previous definition of textBoxHasText.
interface IValidationRule {
bool IsValid { get; }
}
class BoxHasText : IValidationRule {
TextBox _c;
public BoxHasText(TextBox c) { _c = c; }
public bool IsValid {
get { return _c.Text.Length > 0; }
}
}
Well, simply, if you have an Entity class, and you want to use lambda expressions on that Entity to determine if something is valid (returning boolean), you could use a Func.
So, given an Entity:
class Entity
{
public string MyProperty { get; set; }
}
You could define a ValidationRule class for that like this:
class ValidationRule<T> where T : Entity
{
private Func<T, bool> _rule;
public ValidationRule(Func<T, bool> rule)
{
_rule = rule;
}
public bool IsValid(T entity)
{
return _rule(entity);
}
}
Then you could use it like this:
var myEntity = new Entity() { MyProperty = "Hello World" };
var rule = new ValidationRule<Entity>(entity => entity.MyProperty == "Hello World");
var valid = rule.IsValid(myEntity);
Of course, that's just one possible solution.
If you remove the generic constraint above ("where T : Entity"), you could make this a generic rules engine that could be used with any POCO. You wouldn't have to derive a class for every type of usage you need. So if I wanted to use this same class on a TextBox, I could use the following (after removing the generic constraint):
var rule = new ValidationRule<TextBox>(tb => tb.Text.Length > 0);
rule.IsValid(myTextBox);
It's pretty flexible this way. Using lambda expressions and generics together is very powerful. Instead of accepting Func or Action, you could accept an Expression> or Expression> and have direct access to the express tree to automatically investigate things like the name of a method or property, what type of expression it is, etc. And people using your class would not have to change a single line of code.
something like:
class ValidationRule
{
private Func<bool> validation;
public ValidationRule(Func<bool> validation)
{
this.validation = validation;
}
public bool IsValid()
{
return validation();
}
}
would be more C# 3 style but is compiled to the same code as #Frank Krueger's answer.
This is what you asked for, but doesn't feel right. Is there a good reason why the entity can't be extended to perform validation?
Would a rule definition syntax like this one work for you?
public static void Valid(Address address, IScope scope)
{
scope.Validate(() => address.Street1, StringIs.Limited(10, 256));
scope.Validate(() => address.Street2, StringIs.Limited(256));
scope.Validate(() => address.Country, Is.NotDefault);
scope.Validate(() => address.Zip, StringIs.Limited(10));
switch (address.Country)
{
case Country.USA:
scope.Validate(() => address.Zip, StringIs.Limited(5, 10));
break;
case Country.France:
break;
case Country.Russia:
scope.Validate(() => address.Zip, StringIs.Limited(6, 6));
break;
default:
scope.Validate(() => address.Zip, StringIs.Limited(1, 64));
break;
}
Check out DDD and Rule driven UI Validation in .NET for more information