dynamic to concrete type with automapper - c#

I do a post with an anonymous type on an WebApi controller in the body I have this new { Firstname = "AA", Lastname = "BB"}
[HttpPost]
public IHttpActionResult Post([FromBody]dynamic person)
{
}
When I hit the controller, person is not null and I can see the the properties with their data.
In the controller I'd like convert the dynamic type to my concrete type Person
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
}
I tried with Mapper.Initialize(cfg => cfg.CreateMap<dynamic, Person>());
When I do this
var person = Mapper.Map<dynamic, Person>(source);
All the properties of person are null.
Any idea ?
Thanks,

According to the documentation, instead of...
var person = Mapper.Map<dynamic, Person>(source);
...just use...
var person = Mapper.Map<Person>(source);
Full example:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() { return FirstName + " " + LastName; }
}
//Main
Mapper.Initialize( cfg => {} );
dynamic source = new ExpandoObject();
source.FirstName = "Hello";
source.LastName = "World";
var person = Mapper.Map<Person>(source);
Console.WriteLine("GetType()= '{0}' ToString()= '{1}'", person.GetType().Name, person);
Output:
GetType()= 'Person' ToString()= 'Hello World'
Link to DotNetFiddle demo

Related

XUnit Mocking Passing and Asserting a Collection

New to XUnit and attempting to test the following method but test is failing.
I believe the reason is that a new instance of the data is created when the assert is called.
So even thought the results are the same the object reference is not.
When a new record is added to the collection, it is supposed to returned the same record added.
Employee Data Class:
public class EmployeeData
{
public int Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Title { get; set; }
}
Method to test:
public List<EmployeeData> Add(List<EmployeeData> employees)
{
foreach(var employee in employees)
{
data.Add(new EmployeeData() { Id = newId(),
FirstName = employee.FirstName, LastName = employee.LastName,
Title = employee.Title });
}
return data;
}
Test Method:
[Fact]
public void Add()
{
// Arrange
var data = new List<EmployeeData>();
data.Add(new EmployeeData() { Id = 1, FirstName = "Adams", LastName = "John", Title = "Fireman" });
// Mocking the employee class constructor arguments.
var mockLogging = new Mock<ILogger<DataService>>();
var mockConfig = new Mock<IConfiguration>();
var sut = new Employee(mockLogging.Object, mockConfig.Object);
var result = sut.Add(data);
// Assert should return the exact data inputted
Assert.Equal(result, data);
}
Test Result:
Message:
Assert.Equal() Failure
Expected: List<EmployeeData> [EmployeeData { FirstName = "Adams", Id = 1, LastName = "John", Title = "Fireman" }]
Actual: List<EmployeeData> [EmployeeData { FirstName = "Adams", Id = 1, LastName = "John", Title = "Fireman" }]
What does it mean that EmployeeData equals EmployeeData?
You can override Equals methods in the EmployeeData class.
public override bool Equals(object obj)
{
return this.FirstName == ((EmployeeData)obj).FirstName;
}
The second option is to pass IEqualityComparer<T> to the Equal method.
public class GenericCompare<T> : IEqualityComparer<T> where T : class
{
private Func<T, object> _expr { get; set; }
public GenericCompare(Func<T, object> expr)
{
this._expr = expr;
}
public bool Equals(T x, T y)
{
var first = _expr.Invoke(x);
var sec = _expr.Invoke(y);
if (first != null && first.Equals(sec))
return true;
else
return false;
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
}
And use it:
Assert.Equal<EmployeeData>(result, data, new GenericCompare<EmployeeData>(x => x.Id));
Copy pasted GenericCompare from https://stackoverflow.com/a/23623976/6629020

Reflection of object properties

i have this code
public class ParameterOrderInFunction : Attribute
{
public int ParameterOrder { get; set; }
public ParameterOrderInFunction(int parameterOrder)
{
this.ParameterOrder = parameterOrder;
}
}
public interface IGetKeyParameters
{
}
public class Person: IGetKeyParameters
{
[ParameterOrderInFunction(4)]
public string Age { get; set; }
public string Name { get; set; }
[ParameterOrderInFunction(3)]
public string Address { get; set; }
[ParameterOrderInFunction(2)]
public string Language { get; set; }
[ParameterOrderInFunction(1)]
public string City { get; set; }
public string Country { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Address = "my address";
person.Age = "32";
person.City = "my city";
person.Country = "my country";
Test t = new Test();
string result = t.GetParameter(person);
//string result = person.GetParameter();
Console.ReadKey();
}
}
public class Test
{
public string GetParameter(IGetKeyParameters obj)
{
string[] objectProperties = obj.GetType()
.GetProperties()
.Where(p => Attribute.IsDefined(p, typeof(ParameterOrderInFunction)))
.Select(p => new
{
Attribute = (ParameterOrderInFunction)Attribute.GetCustomAttribute(p, typeof(ParameterOrderInFunction), true),
PropertyValue = p.GetValue(this) == null ? string.Empty : p.GetValue(this).ToString()
})
.OrderBy(p => p.Attribute.ParameterOrder)
.Select(p => p.PropertyValue)
.ToArray();
string keyParameters = string.Join(string.Empty, objectProperties);
return keyParameters;
}
}
What i am trying to do is to get properties values as one string with some order .
it work fine if i put the function GetParameter inside the Person class.
however, i want to use the function GetParameter with other class as well,
so i create empty interface.
Now i want that every object that is of type IGetKeyParameters can use the function.
but i am getting exception in the line:
PropertyValue = p.GetValue(this) == null ? string.Empty : p.GetValue(this).ToString()
You should change loading properties from this (that doesn't have such properties) to parameter object:
PropertyValue = p.GetValue(obj) == null ? string.Empty : p.GetValue(obj).ToString()
You are passing the wrong reference as parameter to the method, you need to pass the object which you used to get the type and properties, so change:
p.GetValue(this) // this means pass current instance of containing class i.e. Test
to:
p.GetValue(obj)
Your statement p.GetValue(this) currenly means to pass the current instance of class Test as parameter which is i am pretty sure not what you want.
in your example code.

Why aren't my values passed to the properties of my class?

So I have a class:
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public Person()
{
AddPerson();
}
private void AddPerson()
{
string fn = this.Firstname;
string ln = this.Lastname;
// Do something with these values
// Probably involves adding to a database
}
}
And I have some code that will instantiate an object and add it to the database, returning the the object of type Person:
Person me = new Person()
{
Firstname = "Piers",
Lastname = "Karsenbarg"
};
However, when I debug this, and get to the AddPerson() method, the properties this.Firstname and this.Lastname don't have anything in them (in this case are empty).
Where am I going wrong?
This is because properties are assigned after constructor is called. Basicaly, this:
Person me = new Person()
{
Firstname = "Piers",
Lastname = "Karsenbarg"
};
is the same as:
Person me = new Person();
me.Firstname = "Piers";
me.Lastname = "Karsenbarg";
Only difference here is syntax. In your case you may want to pass those variables via parametrized constructor (new Person("Piers", "Karsenbarg")).
You have not assigned any values to your properties. I would suggest passing in the names you want in the constructor:
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public Person(string firstname, lastname)
{
this.Firstname = firstname;
this.Lastname = lastname;
AddPerson();
}
private void AddPerson()
{
string fn = this.Firstname;
string ln = this.Lastname;
// Do something with these values
// Probably involves adding to a database
}
}
A person cannot exist without a firstname or lastname so this makes logical sense

Uppercase a List of object with LINQ

I have the code below. I'd like to convert all items in this list to uppercase.
Is there a way to do this in Linq ?
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class MyClass
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
}
Update
I don't want to loop or go field by field. Is there a way by reflection to uppercase the value for each property?
Why would you like to use LINQ?
Use List<T>.ForEach:
myList.ForEach(z =>
{
z.FirstName = z.FirstName.ToUpper();
z.LastName = z.LastName.ToUpper();
});
EDIT: no idea why you want to do this by reflection (I wouldn't do this personally...), but here's some code that'll uppercase all properties that return a string. Do note that it's far from being perfect, but it's a base for you in case you really want to use reflection...:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public static class MyHelper
{
public static void UppercaseClassFields<T>(T theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var property in theInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var theValue = property.GetValue(theInstance, null);
if (theValue is string)
{
property.SetValue(theInstance, ((string)theValue).ToUpper(), null);
}
}
}
public static void UppercaseClassFields<T>(IEnumerable<T> theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var theItem in theInstance)
{
UppercaseClassFields(theItem);
}
}
}
public class Program
{
private static void Main(string[] args)
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
MyHelper.UppercaseClassFields<Person>(myList);
Console.ReadLine();
}
}
LINQ does not provide any facilities to update underlying data. Using LINQ, you can create a new list from an existing one:
// I would say this is overkill since creates a new object instances and
// does ToList()
var updatedItems = myList.Select(p => new Person
{
FirstName = p.FirstName.ToUpper(),
LastName = p.LastName.ToUpper(),
Age = p.Age
})
.ToList();
If using LINQ is not principal, I would suggest using a foreach loop.
UPDATE:
Why you need such solution? Only one way of doing this in generic manner - reflection.
the Easiest approach will be to use ConvertAll:
myList = myList.ConvertAll(d => d.ToUpper());
Not too much different than ForEach loops the original list whereas ConvertAll creates a new one which you need to reassign.
var people = new List<Person> {
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
people = people.ConvertAll(m => new Person
{
FirstName = m.FirstName?.ToUpper(),
LastName = m.LastName?.ToUpper(),
Age = m.Age
});
to answer your update
I don't want to loop or go field by field. Is there a way by
reflection to uppercase the value for each property?
if you don't want to loop or go field by field.
you could use property on the class to give you the Uppercase like so
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string FirstNameUpperCase => FirstName.ToUpper();
public string LastNameUpperCase => LastName.ToUpper();
}
or you could use back field like so
public class Person
{
private string _firstName;
public string FirstName {
get => _firstName.ToUpper();
set => _firstName = value;
}
private string _lastName;
public string LastName {
get => _lastName.ToUpper();
set => _lastName = value;
}
public int Age { get; set; }
}
You can only really use linq to provide a list of new objects
var upperList = myList.Select(p=> new Person {
FirstName = (p.FirstName == null) ? null : p.FirstName.ToUpper(),
LastName = (p.LastName == null) ? null : p.LastName.ToUpper(),
Age = p.Age
}).ToList();
p.lastname.ToString().ToUpper().Contains(TextString)

C# | Linq | SubSonic - Class object

I have this class/object below:
public class Person
{
public string FirstName;
public string MI;
public string LastName;
}
Person p=new Person();
p.FirstName = "Jeff";
p.MI = "A";
p.LastName = "Price";
Is there any built in in linq or c# or in subsonic that will create an output of this?:
string myString = "FirstName=\"Jeff\" p.MI=\"A\" p.LastName=\"Price\"";
It seems you need a ToString overload in Person. Also, don't expose public fields like that. Use properties.
public class Person
{
public string FirstName { get; set; }
public string MI { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return "FirstName=\"" + FirstName + "\" p.MI=\"" + MI + "\" p.LastName=\"" + LastName + "\"";
}
}
(edit)
Here's your request (but it requires properties):
public static class ObjectPrettyPrint
{
public static string ToString(object obj)
{
Type type = obj.GetType();
PropertyInfo[] props = type.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var prop in props)
{
sb.Append(prop.Name);
sb.Append("=\"");
sb.Append(prop.GetValue(obj, null));
sb.Append("\" ");
}
return sb.ToString();
}
}
Usage:
Console.WriteLine(ObjectPrettyPrint.ToString(new Person { FirstName, = "A", MI = "B", LastName = "C" }));
Well, as for LINQ and C#, not by default.
However, in the Person class you can override the ToString() event to do it for you.
public override string ToString()
{
return string.Format("p.Firstname={0} p.MI={1} p.LastName={2}", FirstName, MI, LastName);
}
And then you would just call it as follows:
string myString = p.ToString();
Which will give you the output you are looking for.

Categories

Resources