How to break apart multiple levels of member access - c#

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).

Related

I want to implement a linq expression that will allow me to test an property on a supplied object

I want to implement this method from MOQ. (Little out of my depth here)
ISetup<T> Setup(Expression<Action<T>> expression);
public class Foo {
public string Bar { get; set; }
public int Baz { get; set; }
}
public class MyCoolClass
{
public ? Evaluate<Expression<Action>>(expression);
//I want to be able to access and test the value of Foo.Bar (see below)
}
public class ClientOfMyClass
{
public void UseTheMethod()
{
MyCoolClass myCool = new MyCoolClass();
bool result = myCool.Evaluate<Foo>(f => f.Bar);
}
}
Basically, I am trying to write a method that will allow the caller to specify a property on an object with an expression, and allow me to test the value of that property and do something with it.
You want to use an Expression<Func<>> parameter, and check that it contains a Body, and a Member of type PropertyInfo, and use GetValue() passing your object in.
public static void Evaluate<TObj,TProp>(
this TObj obj,
Expression<Func<TObj, TProp>> expr)
{
var prop = (expr.Body as MemberExpression)?.Member as PropertyInfo;
var val = prop?.GetValue(obj);
if (val != null) {
//Do something
}
}
Note that the above code requires the passed in lambda to point to a Property. If you want to handle Fields as well as Methods, they will come in as different types of Expressions, and you'll want to handle handle them slightly differently. For more context and usage, here's a Fiddle.
Edit: Updated to work with other property types.

How to validate the properties of a class hierarchy with a list of property names

I have a class structure like the following
public Class A
{
public B b;
public C c;
public string strA;
}
public Class B
{
public D d;
public string strB;
}
public Class C
{
public string strC1;
public string strC2;
}
public Class D
{
public string strD1;
public string strD2;
}
For an object of class A,
A objA
I need to validate for example :
objA.b.strB
objA.b.D.strD2
objA.c.strC1
that they are nonempty strings. (Of course, it should be validated that the objects objA.b, objA.b.d and objA.c are not null)
I want to realize it with a method like
public bool ValidatePropertiesWithList(object obj, List<string> listOfFieldNamesToValidate, out string nameOfThePropertyThatViolatesTheValidation)
So I want to validate that the properties with the names in listOfFieldNamesToValidate are not empty, and return with an out parameter the name of the property (if any) that violates this.
Should I use Reflection to realize this validation or are Validation Attributes a better choice for me?
Using obj.GetType().GetProperties() seems to be a good place to start but I dont know how I can handle the hierarchical structure of the classes.
Is it possible to mark the properties of the classes with property attributes so that I can get rid of the listOfFieldNamesToValidate parameter in an elegant way?
Using a list of property names or Attributes solves very different problems:
A list of names should be used if its not known at compile time what properties should be validated; the caller is who knows and therefore its he who must supply the needed info.
Using Attributes necessarily means that someone knows at compile time the properties that need validation (this someone is, in the general case, not you; think in a plug-in scenario). Attributes are really handy to manage code scalability reducing dependencies and coupling; changing validation implementations when more classes, properties, validation rules, etc. appear can be very bug prone. Adding a simple Attribute to the new properties is relatively easy and hard to mess up.
Supposing the Attribute path is the one you really want, I've implemented a general case validator that does a couple of nifty things:
It automatically validates all properties marked with the specified Attribute.
It allows you to define validation rules for different property types.
It will not only match exact types, it will also use any valid reference conversions when searching for an applicable rule; for instance an object rule would be applied to a string property if no other rule with a more specific match is found. Note that this will not work with user defined implict conversions; an int rule will not be covered by a long rule and so on. This feature can be disabled.
I haven't tested this extensively but it should work reasonably well:
[AttributeUsage(AttributeTargets.Property)]
public class ValidateAttribute: Attribute
{
}
public class Validator<TAttribute> where TAttribute : Attribute
{
private readonly Dictionary<Type, Predicate<object>> rules;
public Validator()
{
rules = new Dictionary<Type, Predicate<object>>();
}
public bool UnregisterRule(Type t) => rules.Remove(t);
public void RegisterRule<TRule>(Predicate<TRule> rule) => rules.Add(typeof(TRule), o => rule((TRule)o));
public bool Validate<TTarget>(TTarget target, IList<string> failedValidationsBag, bool onlyExactTypeMatchRules = false)
{
var valid = true;
var properties = typeof(TTarget).GetProperties().Where(p => p.GetCustomAttribute<TAttribute>() != null);
foreach (var p in properties)
{
var value = p.GetValue(target);
Predicate<object> predicate = null;
//Rule aplicability works as follows:
//
//1. If the type of the property matches exactly the type of a rule, that rule is chosen and we are finished.
// If no exact match is found and onlyExactMatchRules is true no rule is chosen and we are finished.
//
//2. Build a candidate set as follows: If the type of a rule is assignable from the type of the property,
// add the type of the rule to the candidate set.
//
// 2.1.If the set is empty, no rule is chosen and we are finished.
// 2.2 If the set has only one candidate, the rule with that type is chosen and we're finished.
// 2.3 If the set has two or more candidates, keep the most specific types and remove the rest.
// The most specific types are those that are not assignable from any other type in the candidate set.
// Types are removed from the candidate set until the set either contains one single candidate or no more
// progress is made.
//
// 2.3.1 If the set has only one candidate, the rule with that type is chosen and we're finished.
// 2.3.2 If no more progress is made, we have an ambiguous rules scenario; there is no way to know which rule
// is better so an ArgumentException is thrown (this can happen for example when we have rules for two
// interfaces and an object subject to validation implements them both.)
Type ruleType = null;
if (!rules.TryGetValue(p.PropertyType, out predicate) && !onlyExactTypeMatchRules)
{
var candidateTypes = rules.Keys.Where(k => k.IsAssignableFrom(p.PropertyType)).ToList();
var count = candidateTypes.Count;
if (count > 0)
{
while (count > 1)
{
candidateTypes = candidateTypes.Where(type => candidateTypes.Where(otherType => otherType != type)
.All(otherType => !type.IsAssignableFrom(otherType)))
.ToList();
if (candidateTypes.Count == count)
throw new ArgumentException($"Ambiguous rules while processing {target}: {string.Join(", ", candidateTypes.Select(t => t.Name))}");
count = candidateTypes.Count;
}
ruleType = candidateTypes.Single();
predicate = rules[ruleType];
}
}
valid = checkRule(target, ruleType ?? p.PropertyType, value, predicate, p.Name, failedValidationsBag) && valid;
}
return valid;
}
private bool checkRule<T>(T target, Type ruleType, object value, Predicate<object> predicate, string propertyName, IList<string> failedValidationsBag)
{
if (predicate != null && !predicate(value))
{
failedValidationsBag.Add($"{target}: {propertyName} failed validation. [Rule: {ruleType.Name}]");
return false;
}
return true;
}
}
And you'd use it as follows:
public class Bar
{
public Bar(int value)
{
Value = value;
}
[Validate]
public int Value { get; }
}
public class Foo
{
public Foo(string someString, ArgumentException someArgumentExcpetion, Exception someException, object someObject, Bar someBar)
{
SomeString = someString;
SomeArgumentException = someArgumentExcpetion;
SomeException = someException;
SomeObject = someObject;
SomeBar = someBar;
}
[Validate]
public string SomeString { get; }
[Validate]
public ArgumentException SomeArgumentException { get; }
[Validate]
public Exception SomeException { get; }
[Validate]
public object SomeObject { get; }
[Validate]
public Bar SomeBar { get; }
}
static class Program
{
static void Main(string[] args)
{
var someObject = new object();
var someArgumentException = new ArgumentException();
var someException = new Exception();
var foo = new Foo("", someArgumentException, someException, someObject, new Bar(-1));
var validator = new Validator<ValidateAttribute>();
var bag = new List<string>();
validator.RegisterRule<string>(s => !string.IsNullOrWhiteSpace(s));
validator.RegisterRule<Exception>(exc => exc == someException);
validator.RegisterRule<object>(obj => obj == someObject);
validator.RegisterRule<int>(i => i > 0);
validator.RegisterRule<Bar>(b => validator.Validate(b, bag));
var valid = validator.Validate(foo, bag);
}
}
And of course, bag's content is the expected:
Foo: SomeString failed validation. [Rule: String]
Foo: SomeArgumentException failed validation. [Rule: Exception]
Bar: Value failed validation. [Rule: Int32]
Foo: SomeBar failed validation. [Rule: Bar]

C# : LINQ query to list all empty properties of a class

I have a class like this :
public class Test
{
public string STR1{ get; set; }
public INT INT1{ get; set; }
public DOUBLE DBL1{ get; set; }
public DATETIME DT1{ get; set; }
}
Normally, before saving the object, i will have to check all the properties inside this Class, and return a warning message if there is any empty/null property. There is easy way to do this by simply check each property like this :
if (string.IsNullOrEmpty(t.STR1))
return "STR1 is empty"
if (t.INT1 == 0)
return "INT1 = 0";
if (t.DBL1 == 0)
return "DBL1 = 0";
if (t.DT1 == DateTime.MinValue)
return "DT1 is empty"
But what if my class has more properties, actually it contains about 42 properties now, and still growing up. So i was thinking for a "cleaner" way to perform this check, and i found this topic which is quiet similar to my issue : Reflection (?) - Check for null or empty for each property/field in a class?
But this solution does not meet my need as i have to list the values that = null/empty string/0/DateTime.MinValue
Believe me, i wanted to post my "tried code" but i can't figure out a sensible LINQ query for this task (i'm a novice in C#)
Any help is greatly appreciated !
Since you need to test objects of different types, you can combine the solution from the linked question with use of dynamic to dispatch to the proper method.
First, define an overloaded method for each type.
private static IsEmpty(string s) { return string.IsNullOrEmpty(s); }
private static IsEmpty(double f) { return f == 0.0; }
private static IsEmpty(int i) { return i == 0; }
private static IsEmpty(DateTime d) { return d == DateTime.MinValue; }
Now you can use these methods in your check:
List<string> emptyProperties = typeof(MyType).GetProperties()
.Select(prop => new { Prop = prop, Val = prop.GetValue(obj, null) } )
.Where(val => IsEmpty((dynamic)val.Val) // <<== The "magic" is here
.Select(val => val.Prop.Name)
.ToList();
The tricky part of the code casts the value to dynamic, and then tells the runtime to find the most appropriate IsEmpty method for it. The downside to this approach is that the compiler has no way of telling whether the method is going to be found or not, so you may get exceptions at runtime for properties of unexpected type.
You can prevent these failures by adding a catch-all method taking object, like this:
private static IsEmpty(object o) { return o == null; }

Can I evaluate an expression in a way to determine and possibly set a property that is null?

I have a service that takes an object and based on the properties within will perform different actions; with this any of these properties can be null, meaning don't perform this action.
I am trying to create a very simple to use API to do this in cases where some properties can be multiple levels deep, here is an example of the current implementation
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent = DataFactory.GetNewData<SomeParentInfo>(),
data => data.SomeParent.SomeProperty = "someValue" ));
This is a slightly simplified version and in real cases I some times have to setup multiple parent properties this way in order to set one string property at the bottom.
What I would like to do is adjust the code within the GetNewData method to handle instantiating these properties as needed so that the code could look like this:
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent.SomeProperty = "someValue" ));
Here is my current code for GetNewData:
public static T GetNewData<T>(params Action<T>[] actions)
{
var data = Activator.CreateInstance<T>();
foreach (var action in actions)
{
try
{
action(data);
}
catch (NullReferenceException)
{
throw new Exception("The property you are attempting to set is within a property that has not been set.");
}
}
return data;
}
My first thought is to change the params array to be Expression<Action<T>>[] actions and somehow get a member expression for any of these parents that are null, which would allow me to use the activator to create an instance. However my experience with the more advanced features of Expression trees is slim at best.
The reason for attempting to make this API as simplistic as possible is that it is a UI testing framework that will eventually be used by non developers.
Edit:
I want to add one further example of the current implementation to hopefully demonstrate that what I'm trying to do will provide for more readable code, yes there is a very slight 'side-effect' if I can pull this off but I would argue it is a helpful one.
ExampleDataFactory.GetNewData<ServicesAndFeaturesInfo>(
x => x.Property1 = ExampleDataFactory.GetNewData<Property1Type>(),
x => x.Property1.Property2 = ExampleDataFactory.GetNewData<Property2Type>(),
x => x.Property1.Property2.Property3 = ExampleDataFactory.GetNewData<Property3Type>(),
x => x.Property1.Property2.Property3.Property4 = true);
Edit 2:
The classes that I'm working with here are generated from Apache Thrift struct definitions and as such I have no control over them to be able to set up some kinda of smart constructor.
After getting an answer on my other question I now have a fully working solution for this, it isn't quite as simple syntax as I was originally aiming for, but it isn't bad.
public static DataBuilder<T> GetNewData<T>() where T : class, new()
{
return new DataBuilder<T>();
}
The DataBuilder Class:
public class DataBuilder<T>
{
public readonly T data;
public DataBuilder()
{
data = Activator.CreateInstance<T>();
}
public DataBuilder(T data)
{
this.data = data;
}
public DataBuilder<T> SetValue<T2>(Expression<Func<T, T2>> expression, T2 value)
{
var mExpr = GetMemberExpression(expression);
var obj = Recurse(mExpr);
var p = (PropertyInfo)mExpr.Member;
p.SetValue(obj, value);
return this;
}
public T Build()
{
return data;
}
public object Recurse(MemberExpression expr)
{
if (expr.Expression.Type != typeof(T))
{
var pExpr = GetMemberExpression(expr.Expression);
var parent = Recurse(pExpr);
var pInfo = (PropertyInfo) pExpr.Member;
var obj = pInfo.GetValue(parent);
if (obj == null)
{
obj = Activator.CreateInstance(pInfo.PropertyType);
pInfo.SetValue(parent, obj);
}
return obj;
}
return data;
}
private static MemberExpression GetMemberExpression(Expression expr)
{
var member = expr as MemberExpression;
var unary = expr as UnaryExpression;
return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}
private static MemberExpression GetMemberExpression<T2>(Expression<Func<T, T2>> expr)
{
return GetMemberExpression(expr.Body);
}
}
The Usage:
ExampleDataFactory.GetNewData<ServicesAndFeaturesInfo>()
.SetValue(x=> x.Property1.EnumProperty, EnumType.Own)
.SetValue(x=> x.Property2.Property3.Property4.BoolProperty, true)
.Build();
I think you could use the ExpandoObject or the ElasticObject.
ExpandoObject as far as I know it will get "transformed" into a dictionary ( Properties => Values ).

Conditional typing in generic method

Consider the following (heavily simplified) code:
public T Function<T>() {
if (typeof(T) == typeof(string)) {
return (T) (object) "hello";
}
...
}
It's kind of absurd to first cast to object, then to T. But the compiler has no way of knowing that the previous test assured T is of type string.
What is the most elegant, idiomatic way of achieving this behavior in C# (which includes getting rid of the stupid typeof(T) == typeof(string), since T is string can't be used)?
Addendum: There is no return type variance in .net, so you can't make a function overload to type string (which, by the way, is just an example, but one reason why association end redefinition in polymorphism, e.g. UML, can't be done in c#). Obviously, the following would be great, but it doesn't work:
public T Function<T>() {
...
}
public string Function<string>() {
return "hello";
}
Concrete Example 1: Because there's been several attacks to the fact that a generic function that tests for specific types isn't generic, I'll try to provide a more complete example. Consider the Type-Square design pattern. Here follows a snippet:
public class Entity {
Dictionary<PropertyType, object> properties;
public T GetTypedProperty<T>(PropertyType p) {
var val = properties[p];
if (typeof(T) == typeof(string) {
(T) (object) p.ToString(this); // magic going here
}
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(val);
}
}
Concrete Example 2: Consider the Interpreter design pattern:
public class Expression {
public virtual object Execute() { }
}
public class StringExpression: Expression {
public override string Execute() { } // Error! Type variance not allowed...
}
Now let's use generics in Execute to allow the caller to force a return type:
public class Expression {
public virtual T Execute<T>() {
if(typeof(T) == typeof(string)) { // what happens when I want a string result from a non-string expression?
return (T) (object) do_some_magic_and_return_a_string();
} else if(typeof(T) == typeof(bool)) { // what about bools? any number != 0 should be True. Non-empty lists should be True. Not null should be True
return (T) (object) do_some_magic_and_return_a_bool();
}
}
}
public class StringExpression: Expressiong {
public override T Execute<T>() where T: string {
return (T) string_result;
}
}
If you're making these types of checks in a generic method, I'd rethink your design. The method is obviously not truly generic - if it were, you wouldn't need specific type checking...
Situations like this typically can be handled more cleanly by a redesign. One alternative is often to provide an overload of the appropriate type. Other design alternatives which avoid the type-specific behavior exist, as well, such as Richard Berg's suggestion of passing in a delegate.
using System;
using System.Collections.Generic;
using System.Linq;
namespace SimpleExamples
{
/// <summary>
/// Compiled but not run. Copypasta at your own risk!
/// </summary>
public class Tester
{
public static void Main(string[] args)
{
// Contrived example #1: pushing type-specific functionality up the call stack
var strResult = Example1.Calculate<string>("hello", s => "Could not calculate " + s);
var intResult = Example1.Calculate<int>(1234, i => -1);
// Contrived example #2: overriding default behavior with an alternative that's optimized for a certain type
var list1 = new List<int> { 1, 2, 3 };
var list2 = new int[] { 4, 5, 6 };
Example2<int>.DoSomething(list1, list2);
var list1H = new HashSet<int> { 1, 2, 3 };
Example2<int>.DoSomething<HashSet<int>>(list1H, list2, (l1, l2) => l1.UnionWith(l2));
}
}
public static class Example1
{
public static TParam Calculate<TParam>(TParam param, Func<TParam, TParam> errorMessage)
{
bool success;
var result = CalculateInternal<TParam>(param, out success);
if (success)
return result;
else
return errorMessage(param);
}
private static TParam CalculateInternal<TParam>(TParam param, out bool success)
{
throw new NotImplementedException();
}
}
public static class Example2<T>
{
public static void DoSomething(ICollection<T> list1, IEnumerable<T> list2)
{
Action<ICollection<T>, IEnumerable<T>> genericUnion = (l1, l2) =>
{
foreach (var item in l2)
{
l1.Add(item);
}
l1 = l1.Distinct().ToList();
};
DoSomething<ICollection<T>>(list1, list2, genericUnion);
}
public static void DoSomething<TList>(TList list1, IEnumerable<T> list2, Action<TList, IEnumerable<T>> specializedUnion)
where TList : ICollection<T>
{
/* stuff happens */
specializedUnion(list1, list2);
/* other stuff happens */
}
}
}
/// I confess I don't completely understand what your code was trying to do, here's my best shot
namespace TypeSquarePattern
{
public enum Property
{
A,
B,
C,
}
public class Entity
{
Dictionary<Property, object> properties;
Dictionary<Property, Type> propertyTypes;
public T GetTypedProperty<T>(Property p)
{
var val = properties[p];
var type = propertyTypes[p];
// invoke the cast operator [including user defined casts] between whatever val was stored as, and the appropriate type as
// determined by the domain model [represented here as a simple Dictionary; actual implementation is probably more complex]
val = Convert.ChangeType(val, type);
// now create a strongly-typed object that matches what the caller wanted
return (T)val;
}
}
}
/// Solving this one is a straightforward application of the deferred-execution patterns I demonstrated earlier
namespace InterpreterPattern
{
public class Expression<TResult>
{
protected TResult _value;
private Func<TResult, bool> _tester;
private TResult _fallback;
protected Expression(Func<TResult, bool> tester, TResult fallback)
{
_tester = tester;
_fallback = fallback;
}
public TResult Execute()
{
if (_tester(_value))
return _value;
else
return _fallback;
}
}
public class StringExpression : Expression<string>
{
public StringExpression()
: base(s => string.IsNullOrEmpty(s), "something else")
{ }
}
public class Tuple3Expression<T> : Expression<IList<T>>
{
public Tuple3Expression()
: base(t => t != null && t.Count == 3, new List<T> { default(T), default(T), default(T) })
{ }
}
}
Can you use as here?
T s = "hello" as T;
if(s != null)
return s;
I can't think of an "elegant" way to do this. As you say, the compiler can't know that the conditional has ensured that the type of T is string. As a result, it has to assume that, since there's no generalized way to convert from string to T, it's an error. object to T might succeed, so the compiler allows it.
I'm not sure I'd want an elegant way to express this. Although I can see where it'd be necessary to do explicit type checks like this in some situations, I think I'd want it to be cumbersome because it really is a bit of a hack. And I'd want it to stick out: "Hey! I'm doing something weird here!"
Ok, I took a run at it from several different angles and came up short. I would have to conclude that if your current implementation gets the job done you should take the win and move on. Short of some arcane emissions what you got is what you get.
But the compiler has no way of knowing
that the previous test assured T is of
type string.
Umm.... If I am not mistaken, generics is just code gen. The compiler generates a matching method for each distinct type found in the calling methods. So the compiler does know the type argument for the overload being called. Again; If I am not mistaken.
But overall, i think you are misusing the generic in this case, from what I can see, and as others have stated, there are more appropriate solutions..... which are unnamable unless you post code that completely specifies your requirements.
just my 2 pesos...

Categories

Resources