Compare two Complex Objects in c# - c#

I am trying to compare two objects and want to identify the difference in objects.
It works fine if I don't use List. But when I use List, Although the List in both objects are equal, it says it's not equal and go to check for List difference. Since, for now, I don't have the condition for list comparison it crashes and gives me this exception System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'
I have taken help from one of the stackoverflow post from here. Here is my code which I have written so far.
public class Program
{
public static void Main()
{
Employee emp1 = OldEmployee();
Employee emp2 = NewEmployee();
var list = GetDifferingProperties(emp1, emp2);
foreach (var s in list)
Console.WriteLine(s);
}
public static IList<string> GetDifferingProperties(object source, object target)
{
var sourceType = source.GetType();
var sourceProperties = sourceType.GetProperties();
var targetType = target.GetType();
var targetProperties = targetType.GetProperties();
var result = new List<string>();
foreach (var property in
(from s in sourceProperties
from t in targetProperties
where s.Name == t.Name &&
s.PropertyType == t.PropertyType &&
!Equals(s.GetValue(source, null), t.GetValue(target, null))
select new { Source = s, Target = t }))
{
// it's up to you to decide how primitive is primitive enough
if (IsPrimitive(property.Source.PropertyType))
{
result.Add(property.Source.Name);
}
else
{
foreach (var subProperty in GetDifferingProperties(
property.Source.GetValue(source, null),
property.Target.GetValue(target, null)))
{
result.Add(property.Source.Name);
}
}
}
return result;
}
private static bool IsPrimitive(Type type)
{
return type == typeof(string)
|| type == typeof(int) || type == typeof(int?)
|| type == typeof(double) || type == typeof(double?)
|| type == typeof(bool) || type == typeof(bool?)
|| type == typeof(Guid) || type == typeof(Guid?)
|| type == typeof(DateTime) || type == typeof(DateTime?);
}
public static string GetPropertyDisplayName(PropertyInfo pi)
{
var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
return dp != null ? dp.DisplayName : pi.Name;
}
private static Employee NewEmployee()
{
var contactDetail = new ContactDetails();
contactDetail.ContactNumber = "123456789";
var employeeAddress = new Address();
employeeAddress.AddressLine1 = "Microsoft Corporation";
employeeAddress.AddressLine2 = "One Microsoft Way";
employeeAddress.City = "Redmond";
employeeAddress.State = "WA";
employeeAddress.Zip = "98052-6399";
employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };
var employee = new Employee();
employee.FirstName = "Bill";
employee.LastName = "Gates";
employee.MiddleName = "Middle Name";
employee.IsActive = true;
employee.JoinDate = new DateTime(2015, 10, 15);
employee.ReleaseDate = new DateTime(2015, 10, 15);
employee.EmployeeAddress = employeeAddress;
return employee;
}
private static Employee OldEmployee()
{
var contactDetail = new ContactDetails();
contactDetail.ContactNumber = "123456789";
var employeeAddress = new Address();
employeeAddress.AddressLine1 = "Microsoft Corporation";
employeeAddress.AddressLine2 = "One Microsoft Way";
employeeAddress.City = "Redmond";
employeeAddress.State = "WA";
employeeAddress.Zip = "98052-6399";
employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };
var employee = new Employee();
employee.FirstName = "Bill";
employee.LastName = "Gates";
employee.MiddleName = "Middle Name";
employee.IsActive = true;
employee.JoinDate = new DateTime(2015, 10, 15);
employee.ReleaseDate = new DateTime(2015, 10, 15);
employee.EmployeeAddress = employeeAddress;
return employee;
}
}
public class ContactDetails
{
public string ContactNumber { get; set; }
}
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public bool IsActive { get; set; }
public List<ContactDetails> ContactDetails { get; set; }
}
public class Employee
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public DateTime JoinDate { get; set; }
public DateTime? ReleaseDate { get; set; }
public Address EmployeeAddress { get; set; }
}
If I comment out the line employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail }; from oldEmployee and newEmployee, it works fine, and if there is any difference in EmployeeAddress it identifies it, and if there isn't any difference it doesn't. But if I uncomment this line employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail }; it takes out EmployeeAddress as it has difference, although it doesn't. Can some one please suggest what I am missing, I have spent a lot of time to identify the issue.
My Target to Achieve is, to make a list of properties that has a difference in Employee Object, for Example,
If FirstName in Employee has difference result list should
contain only FirstName
If FirstName in Employee and AddressLine1 in EmployeeAddress has difference result list should contain (FirstName, EmployeeAddress)
Similarly, If FirstName in Employee and ContactNumber in ContactDetails which is a List in Address has difference result list should contain (FirstName, EmployeeAddress), In this case result list still contains EmployeeAddress because ContactNumber is in EmployeeAddress which is in Employee, So our main focus is to get parent Properties that has difference is source and target object.
Point 1 and Point 2 are working as Expected. Iff I comment out employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail }; because it causing exception and also it coming with change although it doesn't have any change in source and target.
Any help would be highly appreciated, or you can suggest me some other way of implementation too.

Related

With httpPut to skip that column if .net core is null or null

I am developing micro-service with .NET Core.
The following code is working with an HttpPut request.
But if any field has empty or null value in our incoming JSON request, I want it to retrieve the previous value.
I don't want to constantly run the code below. Is there a short way around this?
if(updateCustomer.Surname != null && updateCustomer.Surname !=string.Empty)
{
customer.Surname = updateCustomer.Surname;
}
var serviceResponse = new ServiceResponse<GetCustomerDto>();
Customer customer = await _context.Customers.FirstOrDefaultAsync(c => c.Id == updateCustomer.Id);
var persons = (from p in _context.Customers where p.Id == updateCustomer.Id select p);
foreach (var person in persons)
{
person.Name = updateCustomer.Name;
person.Surname = updateCustomer.Surname;
person.BusinessCode = "123";
person.Phone = updateCustomer.Phone;
}
await _context.SaveChangesAsync();
serviceResponse.Data = _mapper.Map<GetCustomerDto>(customer);
Following the GetValueOrDefault() idiom from Nullable types, you can create a string extension method to select between two values like so:
public static class StringExtensions
{
public static string GetValueOrDefault(this string str, string alternative)
{
if(string.IsNullOrEmpty(str))
{
return alternative;
}
return str;
}
}
public class Program
{
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public string BusinessCode { get; set; }
public string Phone { get; set; }
}
public static void Main()
{
Person previous = new Person
{
Name = null,
Surname = "Smith",
BusinessCode = "123",
Phone = "(555) 123-4567"
};
Person current = new Person
{
Name = "John",
Surname = string.Empty,
BusinessCode = "321",
Phone = "(555) 765-4321"
};
Person updated = new Person
{
Name = current.Name.GetValueOrDefault(previous.Name),
Surname = current.Surname.GetValueOrDefault(previous.Surname),
BusinessCode = current.BusinessCode.GetValueOrDefault(previous.BusinessCode),
Phone = current.Phone.GetValueOrDefault(previous.Phone)
};
}
}

Orderby on left join null value

Following situation:
Table of users
Table of addresses
The user has a single optional reference to the address table (=left join)
The query to fetch the data is:
IQueryable<User> query =
from u in _dbContext.Users
join a in _dbContext.Address on u.AddressId equals a.Id into address
from addresses in address.DefaultIfEmpty()
select new User(u, a);
Now I want to do a sorting on the query based on the municipality of the address
query = query.OrderBy(u => u.Address.Municipality);
The problem is that the Address can be a null value (as the address is optional) and for that reason it is throwing following exception.
NullReferenceException: Object reference not set to an instance of an object.
Is there a way to order on the municipality knowing that it can be null?
Already tried following things with same outcome:
query = query.OrderBy(u => u.Address.Municipality ?? "");
query = query.OrderBy(u => u.Address == null).ThenBy(u => u.Address.Municipality);
You can use
query = query.OrderBy(u => u.Address.Municipality.HasValue);
You can write your comparer like this:
public class One
{
public int A { get; set; }
}
public class Two
{
public string S { get; set; }
}
public class T
{
public One One { get; set; }
public Two Two { get; set; }
}
public class OrderComparer : IComparer<Two>
{
public int Compare(Two x, Two y)
{
if (((x == null) || (x.S == null)) && ((y == null) || (y.S == null)))
return 0;
if ((x == null) || (x.S == null))
return -1;
if ((y == null) || (y.S == null))
return 1;
return x.S.CompareTo(y.S);
}
}
static void Main(string[] args)
{
var collection = new List<T> {
new T{ One = new One{A=1}, Two = new Two{ S="dd" } },
new T{ One = new One{A=5}, Two = null },
new T{ One = new One{A=0}, Two = new Two{ S=null } },
new T{ One = new One{A=6}, Two = new Two{ S="aa" } },
};
var comparer = new OrderComparer();
collection = collection.OrderBy(e => e.Two, comparer).ToList();
}
But in your case you have to write var collection = query.AsEnumerable().OrderBy(x=>x.Address).
Also there is other method:
var result = query.Where(x=>x.Address==null || x.Address.Municipality==null)
.Union(query.Where(x.Address!=null && x.Address.Municipality!=null).OrderBy(x=>x.Address.Municipality));
I create a simple demo and it works well when I add nullable foreign key to the two tables.
Besides, I do not understabd what is select new User(u, a); in your code.
Below is my sample code:
Models:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Address")]
public int? AddressId { get; set; }
public Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string AddressName { get; set; }
public string Municipality { get; set; }
}
Action:
IQueryable<User> query =
from u in _context.Users
join a in _context.Address on u.AddressId equals a.Id into address
from addresses in address.DefaultIfEmpty()
select new User
{
Id = u.Id,
Name = u.Name,
AddressId = u.AddressId,
Address = addresses
};
query = query.OrderBy(u => u.Address.Municipality);

How merge two lists of different objects?

Using C# with LINQ, how can I merge two lists of different objects, say, Seminar and Conference?
They have some common and some different fields/properties and do not share unique id.
class Seminar
{
int id,
DateTime joinDate,
string name
}
class Conference
{
Guid confNumber,
DateTime joinDate
Type type
}
I have a list of:
List<Seminar>
List<Conference>
I need to merge them into a super List:
List<Object>
A code snippet would be great help.
If you just want a single List<object> containing all objects from both lists, that's fairly simple:
List<object> objectList = seminarList.Cast<object>()
.Concat(conferenceList)
.ToList();
If that's not what you want, then you'll need to define what you mean by "merge".
Following code works fine for me, if this is your definition of Merge
One solution
List<A> someAs = new List<A>() { new A(), new A() };
List<B> someBs = new List<B>() { new B(), new B { something = new A() } };
List<Object> allS = (from x in someAs select (Object)x).ToList();
allS.AddRange((from x in someBs select (Object)x).ToList());
Where A and B are some classes as follows
class A
{
public string someAnotherThing { get; set; }
}
class B
{
public A something { get; set; }
}
Another Solution
List<A> someAs = new List<A>() { new A(), new A() };
List<B> someBs = new List<B>() { new B(), new B { something = string.Empty } };
List<Object> allS = (from x in someAs select (Object)new { someAnotherThing = x.someAnotherThing, something = string.Empty }).ToList();
allS.AddRange((from x in someBs select (Object)new { someAnotherThing = string.Empty, something = x.something}).ToList());
Where A and B are having class definition as
class A
{
public string someAnotherThing { get; set; }
}
class B
{
public string something { get; set; }
}
Simple method of pure code
internal class Person
{
public int Id { get; set; }
public string UserName { get; set; }
}
internal class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
internal class UserPerson
{
public int Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
private static void Main(string[] args)
{
Person[] people = new Person[3] { new Person { Id = 1, UserName = "AliUserName" }, new Person { Id = 2, UserName = "MortezaUserName" }, new Person { Id = 3, UserName = "SalarUserName" } };
User[] users = new User[4] { new User { FirstName = "ali", LastName = "Barzegari" }, new User { FirstName = "Morteza", LastName = "Sefidi" }, new User { FirstName = "Salar", LastName = "Pirzadeh" }, new User { FirstName = "Babak", LastName = "Hasani" } };
UserPerson[] userPeople = new UserPerson[people.Length > users.Length ? people.Length : users.Length];
if (people.Length > users.Length)
for (int i = 0; i < people.Length; i++)
{
userPeople[i] = new UserPerson
{
Id = people[i].Id,
UserName = people[i].UserName,
FirstName = users.Length <= i ? "" : users[i].FirstName,
LastName = users.Length <= i ? "" : users[i].LastName
};
}
else
for (int i = 0; i < users.Length; i++)
{
userPeople[i] = new UserPerson
{
Id = people.Length <= i ? 0 : people[i].Id,
UserName = people.Length <= i ? "" : people[i].UserName,
FirstName = users[i].FirstName,
LastName = users[i].LastName
};
}
Console.ReadLine();
}

Get the differences between 2 lists

I have two lists (ListA and ListB), the type of these lists is the same PersonInfo, the Loginfield is a unique key.
public class PersonInfo
{
public string Login { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public bool Active { get; set; }
}
I'd like compare these two lists :
I'd like get a list of items in ListA not available in ListB
For the items available in both lists, I'd like get a list from ListA (Login field is a unique key) for the item where there is a difference between the two lists.
Example : if for the Login "MyLogin" in ListA, the value of FirstName does not match with the value in ListB. The item with "MyLogin" as Login must be part of the result list.
Example : if the Age between ListA and ListB for a specific login is different, the item must be part of the result
Thanks.
To compare objects of custom data type lists, you will need to implement IEquatable in your class and override GetHashCode()
Check this MSDN Link
Your class
public class PersonInfo : IEquatable<PersonInfo>
{
public string Login { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public bool Active { get; set; }
public bool Equals(PersonInfo other)
{
//Check whether the compared object is null.
if (Object.ReferenceEquals(other, null)) return false;
//Check whether the compared object references the same data.
if (Object.ReferenceEquals(this, other)) return true;
//Check whether the properties are equal.
return Login.Equals(other.Login) && FirstName.Equals(other.FirstName) && LastName.Equals(other.LastName) && Age.Equals(other.Age) && Active.Equals(other.Active);
}
public override int GetHashCode()
{
int hashLogin = Login == null ? 0 : Login.GetHashCode();
int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
int hashLastName = LastName == null ? 0 : LastName.GetHashCode();
int hashAge = Age.GetHashCode();
int hashActive = Active.GetHashCode();
//Calculate the hash code.
return (hashLogin + hashFirstName + hashLastName) ^ (hashAge + hashActive);
}
}
Then here is how you use it (as listed in Pranay's response)
List<PersonInfo> ListA = new List<PersonInfo>() { new PersonInfo { Login = "1", FirstName = "James", LastName = "Watson", Active = true, Age = 21 }, new PersonInfo { Login = "2", FirstName = "Jane", LastName = "Morrison", Active = true, Age = 25 }, new PersonInfo { Login = "3", FirstName = "Kim", LastName = "John", Active = false, Age = 33 } };
List<PersonInfo> ListB = new List<PersonInfo>() { new PersonInfo { Login = "1", FirstName = "James2222", LastName = "Watson", Active = true, Age = 21 }, new PersonInfo { Login = "3", FirstName = "Kim", LastName = "John", Active = false, Age = 33 } };
//Get Items in ListA that are not in ListB
List<PersonInfo> FilteredListA = ListA.Except(ListB).ToList();
//To get the difference between ListA and FilteredListA (items from FilteredListA will be removed from ListA)
ListA.RemoveAll(a => FilteredListA.Contains(a));
EDIT
Try this soltuion for detail difference :
Compare two objects and find the differences
How to: Find the Set Difference Between Two Lists (LINQ)
Enumerable.Except Method (IEnumerable, IEnumerable) -Produces the set difference of two sequences by using the default equality comparer to compare values.
double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.2 };
IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
or
//newList will include all the common data between the 2 lists
List<T> newList = list1.Intersect(list2).ToList<T>();
//differences will be the data not found
List<T> differences = list1.RemoveAll(a => newList.Contains(a));
or
outer join to get difference
var compare1to2 = from a in
from b in driveList2.Where(b => b.property == a.property).DefaultIfEmpty()
select a;
var list3 = list1.Except(list2).ToList(); //List3 contains what in list1 but not _list2.
Try this for objects comparison and loop around it for List<T>
public static void GetPropertyChanges<T>(this T oldObj, T newObj)
{
Type type = typeof(T);
foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
object selfValue = type.GetProperty(pi.Name).GetValue(oldObj, null);
object toValue = type.GetProperty(pi.Name).GetValue(newObj, null);
if (selfValue != null && toValue != null)
{
if (selfValue.ToString() != toValue.ToString())
{
//do your code
}
}
}
}
you can use Zip() and Intersect() from LINQ

.Net Get Property Values of Object by Key, to any depth

I would like to be able to access the value of an object property to any depth having only the string-key of the property. Also, if possible, using collection indexing on List properties.
So, If I have the string "Person.Surname" then I could get the value "Smith" from and instanciated CaseConductor object. So given some setup code like this ...
//- Load a caseConductor
var caseConductor = new CaseConductor();
caseConductor.CaseID = "A00001";
// person
caseConductor.Person = new Person();
caseConductor.Person.Surname = "Smith" ;
caseConductor.Person.DOB = DateTime.Now ;
// case note list
caseConductor.CaseNoteList = new List<Note>();
caseConductor.CaseNoteList.Add(new Note { NoteText = "A-1" , NoteDt = DateTime.Now });
caseConductor.CaseNoteList.Add(new Note { NoteText = "B-2", NoteDt = DateTime.Now });
// I could do this ...
object val = caseConductor.SomeCleverFunction("Person.Surname");
// or this ...
object val = caseConductor.SomeCleverFunction("CaseNoteList[0].NoteText");
Has anyone done this before ?
Here are some setup classes ...
class Note
{
public Guid NoteID { get; set; }
public string NoteText { get; set; }
public DateTime? NoteDt { get; set; }
}
public class Person
{
public Guid PersonID { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public DateTime? DOB { get; set; }
}
class CaseConductor
{
public String CaseID{get;set;}
public Person Person { get; set; }
public List<Note> CaseNoteList { get; set; }
}
Our use case is to iterate over a series of appropriately named content controls in a word dcoument template using open xml sdk 2, and poke values into a newly created word documents, something like this ...
List<SdtElement> ccList = wordprocessingDocument.MainDocumentPart.Document.Descendants<SdtElement>().ToList();
foreach (var cc in ccList)
{
string alias = cc.SdtProperties.GetFirstChild<SdtAlias>().Val.Value;
switch (cc.GetType().Name)
{
case "SdtRun":
SdtRun thisRun = (SdtRun)cc;
//thisRun.Descendants<Text>().First().Text = theValueToBePoked ;
break;
}
}
Use good old reflection. I have tested and this actually works:
public static object GetValue(object o, string propertyName)
{
Type type = o.GetType();
PropertyInfo propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance ).Where(x => x.Name == propertyName).FirstOrDefault();
if(propertyInfo!=null)
{
return propertyInfo.GetValue(o, BindingFlags.Instance, null, null, null);
}
else
{
return null; // or throw exception
}
}
I'm assuming that
caseConductor.SomeCleverFunction
is not a static method, and has access to the Person object, and that the Person object itself if a public property.
I'm also assuming that you want to pass a string like "prop.address.street" where each sub property is an class that containts a puplic property with that name
Split the string input on the period, find the left most string
Use reflection to get a list of properties ( typeof(caseconductor).GetProperties() )
Find the matching property, call GetValue on it, passing the last known solid object (starting with 'this') and storing a refernce to it.
if there is more sub properties in the string left, repeat to step 1, removing the left most part of the string.
otherwise, call GetValue() on the property, using the last GetValue() return object from step 3, and return it.
Something like:
"prop.address.street" -> find property "prop" from 'this' and GetValue,
there is still more "."'s so repeat, storing return value
"address.street" -> find property "address" from the last returned GetValue, and get it's value.
there is still more "."'s so repeat, storing return value
"street" -> find property "street" from the last returned GetValue, and return it's value.
End of string, return last value
Edit -
This is pretty rough, but toss it into LinqPAD and take a look.
http://www.linqpad.net/
Edit #2 - you should be able to index into arrays using the ^ syntax below.
Again this is reaaaaaaaaally rough, just enough to get a working example.
Edit #3 - Cleaned up the example slightly and changed it from my example classes to yours.
void Main()
{
//- Load a caseConductor
var caseConductor = new CaseConductor();
caseConductor.CaseID = "A00001";
// person
caseConductor.Person = new Person();
caseConductor.Person.Surname = "Smith" ;
caseConductor.Person.DOB = DateTime.Now ;
// case note list
caseConductor.CaseNoteList = new List<Note>();
caseConductor.CaseNoteList.Add(new Note { NoteText = "A-1" , NoteDt = DateTime.Now });
caseConductor.CaseNoteList.Add(new Note { NoteText = "B-2", NoteDt = DateTime.Now });
// I could do this ...
string val1 = caseConductor.GetPropertyValue<string>("Person.Surname");
// or this ...
Note val2 = caseConductor.GetPropertyValue<Note>("CaseNoteList^1");
val1.Dump("val1"); //this is a string
val2.Dump("val2"); //this is a Note
}
public static class extensions
{
public static T GetPropertyValue<T>(this object o,string Properties) where T:class
{
var properties = Properties.Split('.');
var indexsplit = properties[0].Split('^');
var current = indexsplit[0];
var prop = (from p in o.GetType().GetProperties() where p.Name == current select p).Take(1).Single();
var val = prop.GetValue(o,null);
if(indexsplit.Length>1)
{
var index = int.Parse(indexsplit[1]);
IList ival = (IList)val;
val = ival[index];
}
if(properties[0] == Properties)
return (T)val;
else
return val.GetPropertyValue<T>(Properties.Replace(properties[0]+".",""));
}
}
class Note
{
public Guid NoteID { get; set; }
public string NoteText { get; set; }
public DateTime? NoteDt { get; set; }
}
public class Person
{
public Guid PersonID { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public DateTime? DOB { get; set; }
}
class CaseConductor
{
public String CaseID{get;set;}
public Person Person { get; set; }
public List<Note> CaseNoteList { get; set; }
}
OK, I came up with something which continues Aliosted and asowyer start suggestions, here it is. You can see I still having trouble with the index access of composed objects. Thnaks for your help.
#region object data ...
var model = new HcmlDocumentProductionModel();
model.CaseID = "A001";
model.CaseConductor = new CaseConductor();
model.CaseConductor.AField = "AField";
model.CaseConductor.Person = new Person();
model.CaseConductor.Person.Surname = "{Smith}";
model.CaseConductor.Person.DOB = DateTime.Now;
model.CaseConductor.CaseNoteList = new List<Note>();
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "A-1", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.CaseNote });
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "B-2", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.ReferralNote });
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "C-3", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.StatusNote });
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "d-3", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.CaseNote });
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "e-3", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.StatusNote });
model.CaseConductor.CaseNoteList.Add(new Note { NoteText = "f-3", NoteDt = DateTime.Now, NoteTypeEnum = NoteTypeEnum.CaseNote });
#endregion
string head = "";
string tail = "";
// tail
tail = "".Tail();
tail = "Surname".Tail();
tail = "Person.Surname".Tail();
tail = "CaseConductor.Person.Surname".Tail();
// head
head = "".Head();
head = "Surname".Head();
head = "Person.Surname".Head();
head = "CaseConductor.Person.Surname".Head();
// ObjectDictionary
//var person = new Person { Surname = "Smith" };
//var d = person.ObjectDictionary();
//object ovalue = d["Surname"];
// get value special
object o2 = model.CaseConductor.Person.ValueByKey("Surname");
object o3 = model.CaseConductor.Person.ValueByKey("DOB");
object o4 = model.CaseConductor.ValueByKey("Person.Surname");
object o5 = model.ValueByKey("CaseConductor.Person.Surname");
// get the list of ...
object o6 = model.ValueByKey("CaseConductor.CaseNoteList");
// get item - index thing does not work - get anull here
string noteText = model.CaseConductor.CaseNoteList[1].NoteText;
object o7 = model.ValueByKey("CaseConductor.CaseNoteList[1].NoteText");
namespace Zed
{
public static class Zed
{
public static object ValueByKey(this object o, string key)
{
if (!String.IsNullOrEmpty(key))
{
if (!key.Contains("."))
{
return (o.ObjectDictionary())[key];
}
else
{
// key contains a dot ; therefore get object by the name of the head
// and pass on that object and get propety by the tail
var d = o.ObjectDictionary();
var head = key.Head();
if (head.Contains("["))
{
string headMinusIndexer = head.Substring(0, head.IndexOf("["));
string indexString = head.Between("[", "]");
int index = Convert.ToInt32(indexString);
object oArray = d[headMinusIndexer];
//List<object> oList= d[headMinusIndexer];
// now get the object with the index, ... and continue
//object el = ((object[])oArray)[index];
return null;
}
else
{
var onext = d[head];
return onext.ValueByKey(key.Tail());
}
}
}
return null;
}
public static Dictionary<string,object> ObjectDictionary(this object o)
{
return o.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(o, null));
}
public static string Head(this string key)
{
var head = String.Empty;
var splittBy = '.';
if (!String.IsNullOrEmpty(key))
{
var keyArray = key.Split(splittBy);
head = keyArray[0];
}
//-Return
return head;
}
public static string Tail(this string key)
{
var tail = "";
var splittBy = '.';
if (!String.IsNullOrEmpty(key))
{
var keyArray = key.Split(splittBy);
for (int i = 1; i < keyArray.Length; i++)
{
tail += (i > 1) ? "." + keyArray[i] : keyArray[i];
}
}
//-Return
return tail;
}
public static string Between(this string head, string start, string end)
{
string between = String.Empty ;
between = head.Substring(head.IndexOf(start) + 1, head.IndexOf(end) - head.IndexOf(start) - 1);
return between;
}
public static object ZGetValue( this object o, string propertyName)
{
Type type = o.GetType();
PropertyInfo propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name == propertyName).FirstOrDefault();
if (propertyInfo != null)
{
return propertyInfo.GetValue(o, BindingFlags.Instance, null, null, null);
}
else
{
return null;
}
}
}
}

Categories