¿Cómo puedo verificar nulos en una expresión profunda de lamda?¿Cómo comprobar los nulos en una expresión lambda profunda?
Digamos por ejemplo tengo una estructura de clases que se anida varias capas de profundidad, y quería ejecutar el siguiente lambda:
x => x.Two.Three.Four.Foo
quiero que vuelva nulo si dos, tres, o cuatro eran nulas , en lugar de arrojar una System.NullReferenceException.
public class Tests
{
// This test will succeed
[Fact]
public void ReturnsValueWhenClass2NotNull()
{
var one = new One();
one.Two = new Two();
one.Two.Three = new Three();
one.Two.Three.Four = new Four();
one.Two.Three.Four.Foo = "blah";
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal("blah", result);
}
// This test will fail
[Fact]
public void ReturnsNullWhenClass2IsNull()
{
var one = new One();
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal(null, result);
}
private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
{
var func = expression.Compile();
var value = func(model);
return value;
}
public class One
{
public Two Two { get; set; }
}
public class Two
{
public Three Three { get; set; }
}
public class Three
{
public Four Four { get; set; }
}
public class Four
{
public string Foo { get; set; }
public string Bar { get; set; }
}
}
ACTUALIZACIÓN:
Una solución sería para coger el NullReferenceException así:
private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
{
TResult value;
try
{
var func = expression.Compile();
value = func(model);
}
catch (NullReferenceException)
{
value = default(TResult);
}
return value;
}
pero odio a incurrir en el gasto de la captura de una excepción que no es, en mi mente, excepcional. Espero que este sea el caso con bastante frecuencia en mi dominio.
ACTUALIZACIÓN 2:
Otra solución sería modificar los captadores propiedad como esta:
public class One
{
private Two two;
public Two Two
{
get
{
return two ?? new Two();
}
set
{
two = value;
}
}
}
que es sobre todo bien para mi dominio, pero hay momentos en los que realmente que se puede esperar de una propiedad para volver nulo. Revisé la respuesta de Josh E como útil, ya que se aproxima bastante a lo que necesito en algunos casos.
esto es mucho más conciso. Tal vez (x => x.Two.Three.Four.Foo); ver http://maybe.codeplex.com/ – Maslow