C# List the class property in lambda expression - c#

I am trying to create an extension method to list the properties in the lambda expression.
Let say there is a Class named Example
public class Example {
Public string Name {get;set;}
Public string Description {get;set;}
}
the extension method can be something like below
public static void GetProperties<T>(this T obj) where T : new()
{
}
Expected usage : this.GetProperties<Example>(m=>m.
so when i type m=>m. should display both the properties (Name,Description).

I think you need to used Func:
public static void GetProperties<T, V>(this T obj, Func<T, V selector) where T : new()
{
}
Usage:
Example ex = new Example();
ex.GetProperties(m => m.Name); // Func<Example, string>
ex.GetProperties(m => m.Description); // Func<Example, string>
I really didn't understand the expected behavior inside the method. But you mentioned m.Name and m.Description. So a property selector is your way.
Func<Example, string> is a function that accepts an Example input parameter and returns a string (which is the property in case of Name and Description).

public static class PropertyUtility
{
public static string GetPropertyName<T>(this T entity, Expression<Func<T, object>> exp)
{
if (exp.Body is MemberExpression) {
return ((MemberExpression)exp.Body).Member.Name;
}
else {
var op = ((UnaryExpression)exp.Body).Operand;
return ((MemberExpression)op).Member.Name;
}
}
}
And use like this:
Example ex = new Example();
var property = ex.GetPropertyName(x => x.Description);

Related

Moq Extended Setup With Single shared Return

What I want to do is to define one or more Setup(s) to one Return call on multiple method calls of the mocked object; hence avoiding multiple single calls to do Setup().Return()s.
The compiler provides an error when attempting the following which demonstrates the goal, so this is not an appropriate way to achieve that goal.
var mPlatform = new Mock<IPlatformCommunicator>();
mPlatform.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()))
.Setup(mp => mp.Start(It.IsAny<Action<IStatus>>()))
...
.Returns(mockStatusIndeterminate.Object as IStatus);
Is there way to define multiple method calls in Setup to economize the total lines of code?
This is not an option too:
.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()) || mp.Start(It.IsAny<Action<IStatus>>()))
As #Nkosi mentions, not really. But there are options that may work depending on your usage.
SetReturnsDefault
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.SetReturnsDefault<string>("This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
Any method that returns a string will return whatever you specify.
The default value provider is similar but across the board.
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.DefaultValueProvider = new MyDefaultValueProvider();
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public class MyDefaultValueProvider : DefaultValueProvider
{
protected override object GetDefaultValue(Type type, Mock mock)
{
return "This is my default value";
}
}
Create your own extension; the following is a working mvp
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.Setup(new Expression<Func<IFoo, string>>[] { x => x.Bar(), x => x.Baz() }, "This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public static class MoqExtensions
{
public static Mock<T> Setup<T, U>(this Mock<T> self, Expression<Func<T, U>>[] setups, U returns)
where T : class
{
foreach (var setup in setups)
{
self.Setup(setup).Returns(returns);
}
return self;
}
}
All of the above produce the following result
You could create your own extension method on Mock<T> that does what you want:
public static class MoqExt {
public static void SetupReturnOnAll<T, TResult>(
this Mock<T> mock,
TResult returnValue,
params Expression<Func<T, TResult>>[] expressions)
where T: class {
foreach (var expr in expressions)
mock.Setup(expr).Returns(returnValue);
}
}
Usage looks like this:
mPlatform
.SetupReturnOnAll(
mockStatusIndeterminate.Object as IStatus,
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()));
With some extra effort to could improve the interface to this:
mPlatform
.SetupAll(
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()))
.Return(mockStatusIndeterminate.Object as IStatus);
For that you'll need an extra class though:
public class MultiSetup<T, TResult>
where T: class {
public Mock<T> Mock { get; }
public Expression<Func<T, TResult>>[] Expressions { get; }
public MultiSetup(Mock<T> mock, Expression<Func<T, TResult>>[] expressions)
=> (Mock, Expressions) = (mock, expressions);
public void Return(TResult returnValue) {
foreach (var expr in Expressions)
Mock.Setup(expr).Returns(returnValue);
}
}
And you'd create it with this extension:
public static class MoqExt {
public static MultiSetup<T, TResult> SetupAll<T, TResult>(
this Mock<T> mock,
params Expression<Func<T, TResult>>[] expressions)
where T : class
=> new MultiSetup<T, TResult>(mock, expressions);
}

How to add a sub property to an Expression?

For example using this classes:
Public class InnerClass
{
string Value {get;set;}
}
public class ObjectClass
{
InnerClass Inner {get; set;}
}
And with a method like this:
public void SomeMethod<TObj, T>(Expression<Func<TObj, T>> exp) where T : InnerClass
{
// ??
}
I need to add "Value" property to the exp.
Calling the method:
SomeMethod(x => x.Inner);
I need to add value to the expression:
x => x.Inner.Value
Tell it what types you're using, otherwise it won't know:
SomeMethod<ObjectClass, InnerClass>(k => k.Inner);
Update your method to
public void SomeMethod<TObject>(Expression<Func<TObject, object>> exp)
{
.....
}
then you can access the property
SomeMethod<ObjectClass>(x => x.Inner.Value);
At the end this work for me:
public void SomeMethod<TObj, T>(Expression<Func<TObj, T>> exp) where T : InnerClass
{
var newExp = Expression.Lambda<Func<TObj, string>>(
Expression.PropertyOrField(exp.Body, "Value"),
exp.Parameters);
// now I can use newExp
}
From here: Adding a node/property to an Expression Tree

Store List of user defined Expressions/Lambdas for type T

The objective here is to allow API consumers to register their model and how to extract data from that model. Using the ValueMapper below we provide a CreateMap method that registers the map name and function to call to retrieve the data as an object.
The idea here being that certain model have a little more work to get the data out correctly. Once the model is registered using CreateMap we'll store that in an internal list/dictionary for future look ups. I've tried a few different angles to solve this problem and this is very close but still is lacking since the caller cannot provide actual expression logic then can only return a straight value.
I've stripped down the code to the bare bones and if there's a better way to solve my problem i'm open to suggestions.
// static class that I would like to hold a list of 'expressions' that can be looked up and executed multuples times by the run time logic
public static class ValueMapper
{
private static Dictionary<string, LambdaExpression> _rules = new Dictionary<string, LambdaExpression>();
public static void CreateMap<T>(string ruleName, Expression<Func<T, object>> valueExpression)
{
_rules.Add(ruleName, valueExpression);
}
}
public class Consumer
{
public Consumer()
{
// This works but doesn't allow for registering further logic
ValueMapper.CreateMap<ExternalUser>("foo", user => user.FirstName);
// This has a compiler error as follows : "A lambda expression with a statement body cannot be converted to an expression tree"
ValueMapper.CreateMap<ExternalUser>("foo", user =>
{
return user.FirstName + user.LastName;
});
}
}
// some external class
public class ExternalUser
{
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
}
From your description it seems you don't need expressions, simple delegates should do:
public static class ValueMapper {
private static Dictionary<string, Func<object, object>> _rules = new Dictionary<string, Func<object, object>>();
public static void CreateMap<T>(string ruleName, Func<T, object> valueFunc) {
_rules.Add(ruleName, c => valueFunc((T) c));
}
}
If there is only one mapping per target type - no need to use strings, use types:
public static class ValueMapper {
private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();
public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
_rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
}
public static object Map<T>(T instance) {
if (_rules.ContainsKey(typeof(T)))
return _rules[typeof(T)](instance);
// or throw here, or return null, depending on what you need
return instance;
}
}
If you know types you are mapping to - use them:
public static class ValueMapper {
private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();
public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
_rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
}
public static TTo Map<TTo>(object instance) {
if (_rules.ContainsKey(instance.GetType()))
return (TTo) _rules[instance.GetType()](instance);
// throw here if necessary
return default(TTo);
}
}

Constructor can't accept input type Expression<Func<T, TResult>> in C#

I want to create the class Foo as follows.
The Foo constructor input expression has to get some member of Type T to do some work.
class Foo<T>
{
public Foo<TResult>(Expression<Func<T, TResult>> selector)
{
List<string> memberNames = typeof(TR).GetProperties().Select(p => p.Name).ToList();
....//some work on memberNames
}
}
and create Foo<T> instance by this code:
Foo<ClassA> foo = new Foo<ClassA>(u=>new{u.Property1, u.Property2});
However, this did not work and gave the following error:
Constructor can't have Generic type TResult.
How can I fix this?
Edit:
After struggling to understand the expression I found an answer and have written it as an answer.
You can move the logic outside of consrtuctor to separate method. Instead of using constructor to create Foo - you can use static method, like this:
class Foo<T> {
private Foo() {
}
private void Init<TResult>(Expression<Func<T, TResult>> selector) {
List<string> memberNames = typeof(TResult).GetProperties().Select(p => p.Name).ToList();
//some work on memberNames
}
public static Foo<T> Create<TResult>(Expression<Func<T, TResult>> selector) {
var foo = new Foo<T>();
foo.Init(selector);
return foo;
}
}
And use it like this:
Foo<ClassA> foo = Foo<ClassA>.Create(u=>new{u.Property1, u.Property2});
I solve that as follow
class ClassA
{
public int MyProperty { get; set; }
public int MyProperty2 { get; set; }
}
class Foo<T>
{
public Foo(Expression<Func<T, Object>> selector)
{
var props = ((NewExpression)selector.Body).Members.Select(p => p.Name).ToList();
}
}
Foo<ClassA> foo = new Foo<ClassA>(u => new { u.MyProperty, u.MyProperty2 });

Get value from Dictionary holding generic type in C#

public class Table<T> where T:SomeClassWithIntegerID
{
private Dictionary<int, T> map = new Dictionary<int, T>();
public bool isInMemory(int id)
{
if (map.ContainsKey(id))
return true;
return false;
}
public T setIt(T obj)
{
map[obj.id] = obj;
}
public T getIt(int id)
{
return map[id];
}
}
Example:
private static Table<User> table = new Table<User>;
class User : SomeClassWithIntegerID
{
public string name { get; set; }
public string password { get; set; }
}
class SomeClassWithIntegerID
{
public int id { get; set; }
}
I can now check if the Table holds a user with a certain ID, because I use that as the key, but there is now no way for me to check if the Table holds a User with the name Bob or whatever. I want to be able to do something like table.isInMemory(name, "bob") but how is that possible with a generic type?
I need to create a function that allows the end user to specify the field and expected value of said field, after which Table will go over all objects of that class, stored in the Dictionary, to see if one has the field that matches that value.
Is this possible at all?
public bool IsInMemory(Func<T, bool> predicate)
{
return map.Values.Any(predicate);
}
You can then call it as:
table.IsInMemory(u => u.Name == "bob");
If you want to use a property name and value to match on you could add an overload:
public bool IsInMemory(string propertyName, object value)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
if(property == null) throw new ArgumentException("Invalid property name: " + propertyName);
var predicate = new Func<T, bool>(item => object.Equals(value, property.GetValue(item, null)));
return IsInMemory(predicate);
}
I would complement Lee's answer with a Where-method to enable querying with LINQ:
public IEnumerable<T> Where(Func<T, bool> predicate)
{
return map.Values.Where(predicate);
}
And an example:
table.Where(x => x.name.Contains("natli"))
.OrderBy(x => x.name);
To answer your actual question, you can (if you're using .NET 4.0) use the dynamic type, which resolves all methods and such at runtime, to call methods or properties that the compiler doesn't know about from its context.
dynamic dynObject = someObject;
dynObject.SomeMethod("Hi there", 27); // Call whatever method or property you "know" exist

Categories