I have this abstract class
public abstract class DisposableList<T> : List<T>, IDisposable
{
protected DisposableList();
public virtual void Dispose();
}
and this Interface
public interface IGroup : IDisposable
{
string Name { get; }
}
I need to test this method
public class MyClass
{
public void MyMethod(IConnection connection)
{
var groups = connection.GetGroups();
var grps = groups.ToDictionary(x => x?.Name); //Here gets System.NullReference exception
}
}
In testing, so far what I did is:
var group1 = new Mock<IGroup>();
group1.SetupGet(c => c.Name).Returns("abc");
var groups = new Mock<DisposableList<IGroup>>();
groups.Object.Add(group1.Object);
Mock<IConnection> connection.Setup(c => c.GetGroups()).Returns(() => groups.Object);
new MyClass().MyMethod(connection);
but var grps = groups.ToDictionary(x => x?.Name); gets System.NullReferenceException: 'Object reference not set to an instance of an object.'
Name is not null and groups is not null. Something happens inside.
how can I fix this?
You can't set null value as dictionary key like this; (It is possible to be null)
groups.ToDictionary(x => x?.Name);
Eliminate the items which is null or has null Name value.
groups.Where(x => x != null && !string.IsNullOrEmpty(x.Name)).ToDictionary(x => x.Name);
Related
I want to pass an instance of a class to a method using an Expression<T> and retrieve the instance from within the method:
public class MyOb
{
public void Receive(Expression<Func<Item>> item)
{
// Here I would like to get item as Item
// Have tried various things such as
var x = ((MemberExpression)(item.Body)).Member;
int y = x.IntProp // should be 123.
}
}
public class Item
{
public int IntProp { get; set; } = 123;
}
MyOb mo = new();
Item myItem = new();
mo.Receive(() => myItem);
That would not be that easy cause compiler will generate a special class to handle closure which will store the value of the local variable (myItem). Something like this should do the trick:
public static void Receive(Expression<Func<Item>> item)
{
if (item.Body is MemberExpression { Expression: ConstantExpression constE })
{
var itemValue = constE.Type.GetFields()
.Where(fi => fi.FieldType.IsAssignableTo(typeof(Item)))
.Single() // possibly proper validation message if multiple found
.GetValue(constE.Value);
var intProp = ((Item)itemValue).IntProp; // your value
Console.WriteLine(intProp); // will print 123 for your code
}
}
I have a abstract class Enumeration which implements the IComparable interface.
public abstract class Enumeration : IComparable
{
[JsonConstructor]
protected Enumeration(int id, string name)
{
Id = id;
Name = name;
}
public int Id { get; }
public string Name { get; }
public static implicit operator Enumeration(string name)
{
return GetAll<Enumeration>().FirstOrDefault(i => i.Name == name);
}
public static IEnumerable<TEnumeration> GetAll<TEnumeration>() where TEnumeration : Enumeration
{
var fields = typeof(TEnumeration).GetFields(
BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
return fields.Select(fieldInfo => fieldInfo.GetValue(null)).Cast<TEnumeration>();
}
I have created SampleStatus.cs class which is inherits from Enumeration.cs class.
public class SampleStatus : Enumeration
{
public static readonly SampleStatus Completed = new SampleStatus(1, nameof(Completed));
public static readonly SampleStatus Deleted = new SampleStatus(2, nameof(Deleted));
public SampleStatus(int id, string name) : base(id, name)
{
}
}
I have created unit test class for SampleStatus.cs class.
[TestMethod]
public void TestMethod()
{
// arrange and act
var result = (Enumeration)SampleStatus.GetAll<SampleStatus>().Single(x => x.Id == 1).Name; // output is returning null.
// assert
Assert.AreEqual("Completed", result);
}
When I call GetAll method which is returning null. I have mocked GetAll and Implicit operator method in the above code.
In provided sample GetAll does not return null (if it did - I would get NullReferenceException). Issue with the sample is in the cast to Enumeration. SampleStatus.GetAll<SampleStatus>().Single(x => x.Id == 1).Name results in Completed which you then cast to Enumeration. Since the implicit conversion exists and the base class does not have definition for Completed (Enumeration)"Completed" ends up being null (i.e. GetAll<Enumeration>().FirstOrDefault(i => i.Name == name))).
You can fix it with removing cast for example:
[TestMethod]
public void TestMethod()
{
// arrange and act
var result = SampleStatus.GetAll<SampleStatus>().Single(x => x.Id == 1).Name; // output is returning null.
// assert
Assert.AreEqual("Completed", result);
}
My repository returns entities derived from a common base class
class BaseClass
{
public int Id { get; set; }
}
class MyClass : BaseClass
{
public string Name { get; set; }
}
class MyOtherClass : BaseClass
{
...
}
in a function like this:
IQueryable<T> GetEntities<T>() where T : BaseClass
I added a method to register additional filters for specific entities as lambdas using Expression<Func<T,bool>> like this:
RegisterFilter<MyClass>(t => t.Name == "Test" );
that will be applied whenever GetEntities is called with MyClass in the type argument.
Question
How can I create an expression dynamically at runtime that wraps a type cast around the filter?
in my specific case GetEntities is called on an IQueryable<MyClass> using the BaseClass as type argument and event tough I know that the filter for MyClass needs to applied I did not find a way to do so:
IQueryable<BaseClass> src =
(new List<MyClass>
{
new MyClass { Id = 1, Name = "asdf" },
new MyClass { Id = 2, Name = "Test" }
})
.AsQueryable();
Expression<Func<MyClass, bool>> filter = o => o.Name == "Test";
// does not work (of course)
src.Where(filter);
Failed attempts
Obviously I could cast the collection back before calling Where but my attempts to do this at runtime did not work:
// HACK: don't look
var genericCast = typeof(Queryable).GetMethod("Cast").MakeGenericMethod(entityType);
var genericWhere = typeof(Queryable).GetMethods().Single(mi => mi.Name == "Where" && mi.GetParameters()[1].ParameterType.GenericTypeArguments[0].Name == "Func`2");
q = (IQueryable<T>)genericCast.Invoke(q, new object[] { genericWhere.Invoke(q, new object[] { filterExp }) });
System.InvalidOperationException: 'Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.'
since this is also very ugly I tried to wrap my filter in cast like this:
LambdaExpression filterExp = (LambdaExpression)filter;
var call = filterExp.Compile();
Expression<Func<T, bool>> wrap = o => (bool)call.DynamicInvoke(Convert.ChangeType(o, entityType));
This works but prevents the filter to be generated into a store expression so it will be done in memory which is also undesirable.
I feel like the solution to this should be trivial but I can't seem to get it right so any help would be appreciated very much.
You can:
// Using SimpleExpressionReplacer from https://stackoverflow.com/a/29467969/613130
public static Expression<Func<BaseClass, bool>> Filter<TDerived>(Expression<Func<TDerived, bool>> test)
where TDerived : BaseClass
{
// x =>
var par = Expression.Parameter(typeof(BaseClass), "x");
// x is TDerived
var istest = Expression.TypeIs(par, typeof(TDerived));
// (TDerived)x
var convert = Expression.Convert(par, typeof(TDerived));
// If test is p => p.something == xxx, replace all the p with ((TDerived)x)
var test2 = new SimpleExpressionReplacer(test.Parameters[0], convert).Visit(test.Body);
// x is TDerived && test (modified to ((TDerived)x) instead of p)
var and = Expression.AndAlso(istest, test2);
// x => x is TDerived && test (modified to ((TDerived)x) instead of p)
var test3 = Expression.Lambda<Func<BaseClass, bool>>(and, par);
return test3;
}
Note that I'm using the SimpleExpressionReplacer I wrote in another answer.
Given a test like:
var exp = Filter<MyClass>(p => p.Name == "Test");
the resulting expression is:
x => x is MyClass && ((MyClass)x).Name == "Test"
Ultimately I want to have an internal interface with a setter and a public one with a getter. The code that replicates this scenario is roughed below:
[TestMethod]
public void TestMethod3()
{
var fake1 = A.Fake<IInterface1>(a => a.Implements(typeof(IInterface2)));
string backingString = null;
IInterface2 fake2 = (IInterface2)fake1;
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("set_Property"))
.Invokes((string param) => { backingString = param; });
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString); //doesn't work
A.CallTo(fake2)
.Where(a => a.Method.Name.Equals("set_Property"))
.Invokes((string param) => { backingString = param; });
A.CallTo(fake2)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString); //doesn't work
fake1.Property = "asdf";
Assert.AreEqual("asdf", fake1.Property); //fails -> fake1.Property is null
Assert.AreEqual(fake1.Property, fake2.Property); //fails -> fake2.Property is null
}
}
public interface IInterface1
{
string Property { get; set; }
}
public interface IInterface2
{
string Property { get; }
}
I could get as far as using backingString to store the setter, but when setting up the getter it doesn't work as I wanted it to.
I also tried something in the line of A.CallTo(() => fake1.Property).Returns(backingString) to no avail.
Would appreciate assistance of them experts :)
When you set up your
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString);
(and similarly for fake2),
the value of backingString is null, so that's what's returned later on when you access the Property getter.
In order to return the value of backingString at the time the Property getter is called, you want ReturnsLazily.
Make this change in each place and the tests pass:
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().ReturnsLazily(() => backingString);
I have an object lets call it ObjectA
and that object has 10 properties and those are all strings.
var myObject = new {Property1="",Property2="",Property3="",Property4="",...}
is there anyway to check to see whether all these properties are null or empty?
So any built-in method that would return true or false?
If any single of them is not null or empty then the return would be false. If all of them are empty it should return true.
The idea is I do not want to write 10 if statement to control if those properties are empty or null.
Thanks
You can do it using Reflection
bool IsAnyNullOrEmpty(object myObject)
{
foreach(PropertyInfo pi in myObject.GetType().GetProperties())
{
if(pi.PropertyType == typeof(string))
{
string value = (string)pi.GetValue(myObject);
if(string.IsNullOrEmpty(value))
{
return true;
}
}
}
return false;
}
Matthew Watson suggested an alternative using LINQ:
return myObject.GetType().GetProperties()
.Where(pi => pi.PropertyType == typeof(string))
.Select(pi => (string)pi.GetValue(myObject))
.Any(value => string.IsNullOrEmpty(value));
I suppose you want to make sure that all properties are filled in.
A better option is probably by putting this validation in the constructor of your class and throw exceptions if validation fails. That way you cannot create a class that is invalid; catch exceptions and handle them accordingly.
Fluent validation is a nice framework (http://fluentvalidation.codeplex.com) for doing the validation. Example:
public class CustomerValidator: AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Property1).NotNull();
RuleFor(customer => customer.Property2).NotNull();
RuleFor(customer => customer.Property3).NotNull();
}
}
public class Customer
{
public Customer(string property1, string property2, string property3)
{
Property1 = property1;
Property2 = property2;
Property3 = property3;
new CustomerValidator().ValidateAndThrow();
}
public string Property1 {get; set;}
public string Property2 {get; set;}
public string Property3 {get; set;}
}
Usage:
try
{
var customer = new Customer("string1", "string", null);
// logic here
} catch (ValidationException ex)
{
// A validation error occured
}
PS - Using reflection for this kind of thing just makes your code harder to read. Using validation as shown above makes it explicitly clear what your rules are; and you can easily extend them with other rules.
The following code returns if any property is not null.
return myObject.GetType()
.GetProperties() //get all properties on object
.Select(pi => pi.GetValue(myObject)) //get value for the property
.Any(value => value != null); // Check if one of the values is not null, if so it returns true.
Here you go
var instOfA = new ObjectA();
bool isAnyPropEmpty = instOfA.GetType().GetProperties()
.Where(p => p.GetValue(instOfA) is string) // selecting only string props
.Any(p => string.IsNullOrWhiteSpace((p.GetValue(instOfA) as string)));
and here's the class
class ObjectA
{
public string A { get; set; }
public string B { get; set; }
}
A slightly different way of expressing the linq to see if all string properties of an object are non null and non empty:
public static bool AllStringPropertyValuesAreNonEmpty(object myObject)
{
var allStringPropertyValues =
from property in myObject.GetType().GetProperties()
where property.PropertyType == typeof(string) && property.CanRead
select (string) property.GetValue(myObject);
return allStringPropertyValues.All(value => !string.IsNullOrEmpty(value));
}
Note if you've got a data structural hierarchy and you want to test everything in that hierarchy, then you can use a recursive method. Here's a quick example:
static bool AnyNullOrEmpty(object obj) {
return obj == null
|| obj.ToString() == ""
|| obj.GetType().GetProperties().Any(prop => AnyNullOrEmpty(prop.GetValue(obj)));
}
To only check if all properties are null:
bool allPropertiesNull = !myObject.GetType().GetProperties().Any(prop => prop == null);
you can use reflection and extension methods to do this.
using System.Reflection;
public static class ExtensionMethods
{
public static bool StringPropertiesEmpty(this object value)
{
foreach (PropertyInfo objProp in value.GetType().GetProperties())
{
if (objProp.CanRead)
{
object val = objProp.GetValue(value, null);
if (val.GetType() == typeof(string))
{
if (val == "" || val == null)
{
return true;
}
}
}
}
return false;
}
}
then use it on any object with string properties
test obj = new test();
if (obj.StringPropertiesEmpty() == true)
{
// some of these string properties are empty or null
}
No, I don't think there is a method to do exactly that.
You'd be best writing a simple method that takes your object and returns true or false.
Alternatively, if the properties are all the same, and you just want to parse through them and find a single null or empty, perhaps some sort of collection of strings would work for you?
You can try the following query :
if the object is "referenceKey" (where few properties may be null )
referenceKey.GetType().GetProperties().Where(x => x.GetValue(referenceKey) == null)
I need to count the properties where the value is set to not Null, so I have used the following query :
var countProvidedReferenceKeys = referenceKey.GetType().GetProperties().Where(x => x.GetValue(referenceKey) != null).Count();