Is the following way of updating an ObservableCollection from another one (both based on the same class) good enough or it better to be done in another way (or just to be improved)?
foreach (MyEntity c in collection2)
{
collection1.Where(p => p.EntID == c.EntID).FirstOrDefault().Field1 = c.Field1;
collection1.Where(p => p.EntID == c.EntID).FirstOrDefault().Field2 = c.Field2;
...
collection1.Where(p => p.EntID == c.EntID).FirstOrDefault().FieldN = c.FieldN;
}
EntID is the primary key.
(Under good enough I mean fast and efficient).
var myItem = collection1.Where(p => p.EntID == c.EntID).FirstOrDefault();
if (myItem == null)
continue;
myItem.Field1 = c.Field1;
myItem.Field2 = c.Field2;
...
myItem.FieldN = c.FieldN;
If myItem and c are different types, have a look at AutoMapper.
As a complementary answer, you can use reflection to copy the N fields from one object to another. I've already talked about this here: How to refactor this? .
You can have your class (SomeClass) implement this code (both objects are the same class):
public void CopyPropertiesFrom(SomeClass SourceInstance)
{
foreach (PropertyInfo prop in typeof(SomeClass).GetProperties())
prop.SetValue(this, prop.GetValue(SourceInstance, null), null);
}
That way, if your class has new properties, you don't have to bother updating the code, it's already there!
For objects with different class, that's also doable via reflection by the property name, but there are some assumptions you have to make (what if property does not exist, what property is different type, what is property value is null, etc.)
Related
I've seen plenty of examples of how to use generic Objects in C#, but can I have a generic property for a static object?
I have 2 distinct lists of Providers:
List<Providers> OldProviders
List<Providers> NewProviders
OldProviders has providers from the database, and NewProviders has providers the user has selected in the View. If any OldProviders aren't in NewProviders, I want to remove them from the database. If any NewProviders aren't in OldProviders, I want to add them to the database. Simple.
One problem:
Provider has 2 properties that correspond to foreign keys important for comparison: StaffID and LicenseID (both integers)
Depending on the choice the user makes, I only care about one of these IDs.
Currently I have 2 sets of helper methods which are completely identical (6 total helpers), except for whether they compare using StaffID or LicenseID. It technically works, but I don't want to maintain it.
Here's an example:
private bool DeleteOldStaffProviders(List<Provider> oldSelectedStaff, List<Provider> newSelectedStaff)
{
foreach (var oldSelected in oldSelectedStaff)
{
bool remove = newSelectedStaff.SingleOrDefault(n => n.StaffID == oldSelected.StaffID) == null;
if (remove)
{
//<remove from database, return false if failure>
}
}
return true;
}
Is there a way I can rewrite this method with a generic parameter reference?
i.e.
newSelectedStaff.SingleOrDefault(n => n.T == oldSelected.T)
where T is either LicenseID or StaffID.
I've seen a lot of examples of people using LINQ and reflection for things kinda similar to this, but I can't seem to figure it out. If you could baby me through it, that would be appreciated.
Yes, use another parameter of type Func<Provider,int> to act as the selector:
private bool DeleteOldStaffProviders(List<Provider> oldSelectedStaff, List<Provider> newSelectedStaff, Func<Provider,Provider,bool> selector)
{
foreach (var oldSelected in oldSelectedStaff)
{
bool remove = newSelectedStaff.SingleOrDefault(n => selector(n) == selector(oldSelected)) == null;
if (remove)
{
//<remove from database, return false if failure>
}
}
return true;
}
usage
DeleteOldStaffProviders(oldStaff, newStaff, x => x.StaffID);
DeleteOldStaffProviders(oldStaff, newStaff, x => x.LicenseID);
You could do it another way - but I think its more clunky. Pass in a Func<Provider,Provider,bool> like this:
DeleteOldStaffProviders(oldStaff, newStaff, (o,n) => o.StaffID == n.StaffID);
And change a line to:
bool remove = newSelectedStaff.SingleOrDefault(n => selector(n,oldSelected))
I am trying to figure out why the following code throws a StackOverflowException (I am finally posting a StackoverflowException in SO!).
Debugging seems to point out that the p.GetValue(this) is generating further calls.
What is actually triggering the infinite call chain ? Is it because p.GetValue(this) ultimately returns an instance of the current object, and thus acts as if constructing a new instance (and every object that constructs itself within its construction will lead to Stackoverflow exceptions) ?
My intent with the following code is to have an object being capable of telling how many of its properties have null/space/empty values.
public class A
{
public string S1 { get; set; }
public string S2 { get; set; }
public int NonInitializedFields
{
get
{
int nonNullFields = 0;
var properties = this.GetType().GetProperties();
foreach (var p in properties)
{
var value = p.GetValue(this);
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
nonNullFields++;
}
return nonNullFields;
}
}
}
//the following throws a StackOverflowException (the construction line itself)
A a1 = new A1{ S1 = "aaa"};
Console.WriteLine(a1.NonInitializedFields);
P.S. My idea originally involves only simple string properties, nothing else, so whatever problems may arise with this approach with other types are not relevant.
You have a property, which, when you execute the "get" accessor, finds all the properties and fetches their value. So it executes itself, recursively.
If you only want string properties, you should check the property type before fetching the value:
var properties = GetType().GetProperties().Where(p => p.PropertyType == typeof(string));
At that point, as your NonInitializedFields property doesn't have a return type of string, it won't be executed.
Personally I would make this a method call rather than a property anyway, mind you. That would also fix the issue, as the method wouldn't find itself when looking for properties.
I would also rename it, as:
A property isn't necessarily backed by a field
A field could be explicitly initialized as null or a reference to a string containing only whitespace
A method called GetNonWhitespaceStringPropertyCount() would be more accurate, IMO. You can also make the whole implementation a LINQ query:
return GetType().GetProperties()
.Where(p => p.PropertyType == typeof(string))
.Select(p => p.GetValue(this))
.Count(v => !string.IsNullOrWhitespace((string) v));
Note that I've fixed the next issue in your code - you're meant to be counting non-null/empty values, but you're actually counting null/empty ones.
I have a class with lots of properties. A shallow copy is enough to fully replicate the object.
I need to compare an object just to check if it contains exactly the same values as another.
My ideas:
The first and most obvious solution is just to create a huge method block that compares each property, one after the other.
The second would be to serialize each object and hash the file or do some sort of md5 checksum on it. (Would this actually work?)
The third is to do some sort of reflection on the object, which would automate the first option, but create an added level of complexity.
Speed isn't really an issue.
I'm interested to hear thoughts, or any other methods I am missing to do such a thing.
Edit:
Thanks all. My solution (Modified to now be recursive on generic items):
public static bool IsSame<T>(T objA, T objB)
{
var type = typeof(T);
var properties = type.GetProperties();
foreach (var pi in properties.Where(a => a.CanRead))
{
if (pi.Name == "Item")
{
var piCount = properties.FirstOrDefault(a => a.Name == "Count");
int count = -1;
if (piCount != null && piCount.PropertyType == typeof(System.Int32))
count = (int)piCount.GetValue(objA, null);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
dynamic child1 = pi.GetValue(objA, new object[] { i });
dynamic child2 = pi.GetValue(objB, new object[] { i });
return IsSame(child1, child2);
}
}
}
else
{
var val1 = type.GetProperty(pi.Name).GetValue(objA, null);
var val2 = type.GetProperty(pi.Name).GetValue(objB, null);
if (val1 != val2 && (val1 == null || !val1.Equals(val2)))
return false;
}
}
return true;
}
Most serializers are designed to ensure that data retains its integrity during serialization and deserialization, not to produce a consistent serialized format. I would avoid using serialization for this purpose.
You may consider implementing IEquatable, to have each instance capable of comparing itself with instances of the same type. Or a class do do the comparisons for you that implements IEqualityComparer. How they do this comparison may be the 'big method' that compares properties one after the other, or uses reflection.
Reflection can be a fairly quick and simple way to achieve your goal but can cause problems down the line (for example if someone adds a property to your type that should not be included for comparing equality), but obviously the converse is also true (someone adds a property that should be checked for equality, but the equality comparison isn't updated). Which approach you use should generally be decided by how comfortable the team is with each approach in tandem with the context in which the class will be used.
In your case I'd probably recommend using the reflection based approach since you wish to check the result of a shallow clone operation, so all properties should be equal.
As an aside, I'd recommend using the MemberwiseClone method to create the clone, which would lessen the need for such stringent tests.
The third option (reflection) would be the slowest, but it would also be the most robust/testable.
The hash code would be very similar to the first option, since you would have to call all of your member variables, so 1 and 2 would require you to update your .Equals(obj) and .GenerateHash() methods every time you modify your member variable lists.
Here is some code to get you started:
foreach (FieldInfo field in this.GetType().GetFields())
{
if (o[field.Name] == null)
{
if (!field.GetValue(this).Equals(o[field.Name]))
return false;
}
else
{
return false;
}
}
return true;
Another thought is that if the properties return simple value types you could group them into immutable value types of their own. For instance, if you have a customer with properties string Address1 string Address2 string City string State string Zip, you could create a value type Address that implements its own equality comparer and use that.
Not sure if this applies to your situation, but I've found that when I have a class with a lot of properties, it is often possible to do this, and it tends to make my classes simpler and easier to reason about.
If you serialize you have to specify the serialization order on each Field/Property to ensure that all data is serialized int the same order. But all you would achieve is to implement GetHashCode() in an external class.
GetHashCode() has some examples on how to override it, so look there first.
If your class has a lot of fields, and you don't want to write all the code by hand. You could use reflection to autogenerate the code. If your class changes from time to time then you could create a partial class with the GetHashCode() implementation in a T4 template.
I'm wondering if there is any functionality built in to C#/LINQ to simplify the following:
foreach(var item in collection)
{
if (item.GetType() == typeof(Type1)
DoType1(item as Type1);
else if (item.GetType() == typeof(Type2))
DoType2(item as Type2);
...
}
to something along the lines of:
collection.ForEachType(Type1 item => DoType1(item), Type2 item => DoType2(item));
I realize that the following is close:
collection.OfType<Type1>.ToList().Foreach(item => DoType1(item));
collection.OfType<Type2>.ToList().Foreach(item => DoType2(item));
But it does not work when the code is dependent on the order of the collection.
The first thing I'd look at is polymorphism; can I instead use a virtual method, and item.DoSomething()?
The next thing I'd look at would be an enum discriminator, i.e.
switch(item.ItemType) {
case ItemType.Foo: ...
case ItemType.Bar: ...
}
(and add the discriminator to the common interface/base-class)
If the types could be anything, then 4.0 has a trick; if you call te method the same thing for every overload, you can get dynamic to worry about picking it:
dynamic x = item;
DoSomething(x);
There's nothing built into LINQ, no. I would caution you against using GetType() like this though - usually it's more appropriate to use is or as followed by a null check:
foreach(var item in collection)
{
Type1 itemType1 = item as Type1;
if (itemType1 != null)
{
DoType1(itemType1);
continue;
}
Type2 itemType2 = item as Type1;
if (itemType2 != null)
{
DoType2(itemType1);
continue;
}
// etc
}
That way derived classes will be treated in a way which is usually the appropriate one.
This sort of type testing is generally frowned upon, mind you - it's generally better to put the behaviour into the type itself as a virtual method, and call it polymorphically.
What about something like:
var typeActions = new Dictionary<Type,Action<Object>>();
typeActions.Add(typeof(Type1), obj => DoType1((Type1)obj));
typeActions.Add(typeof(Type2), obj => DoType2((Type2)obj));
collection.Foreach(obj => typeActions[obj.GetType()](obj));
This code is untested (typed directly into the browser).
Your mileage may vary.
Dictionary<Type, Action<object>> typeMap = new Dictionary<Type, Action<object>>();
typeMap[typeof(Type1)] = item => DoType1(item as Type1);
typeMap[typeof(Type2)] = item => DoType2(item as Type2);
var typeToActionQuery =
from item in source
let type = item.GetType()
where typeMap.ContainsKey(type)
select new
{
input = item;
method = typeMap[type]
};
foreach(var x in typeToActionQuery)
{
x.method(x.input);
}
Here's a version of the matching query which considers derived types (Note, an item may be matched to more than 1 type, and therefore handled multiple times).
var typeToActionQuery =
from item in source
from kvp in typeMap
where kvp.Key.IsInstanceOfType(item)
select new
{
input = item;
method = kvp.Value
};
It seems to me that if you just replace "item.GetType() == typeof( Type1 )" with "item is Type1", your foreach loop will be simple enough.
Not by default. Try Reactive Extensions or Elevate
The Reactive Extensions and Elevate both contain a ForEach implementation. Both have quite a few methods that extend the functionality of linq.
You won't find a ForEachType, but ForEach (Rx or Elevate) and OfType<> (Linq) will give you what you want.
I have a series of about 30 lookup tables in my database schema, all with the same layout (and I would prefer to keep them as separate tables rather than one lookup table), and thus my Linq2SQL context has 30 entities for these lookup tables.
I have a standard class that I would use for CRUD operations on each of these 30 entites, for example:
public class ExampleAttributes : IAttributeList
{
#region IAttributeList Members
public bool AddItem(string Item, int SortOrder)
{
MyDataContext context = ContextHelper.GetContext();
ExampleAttribute a = new ExampleAttribute();
a.Name = Item;
a.SortOrder = SortOrder;
context.ExampleAttributes.InsertOnSubmit(a);
try
{
context.SubmitChanges();
return true;
}
catch
{
return false;
}
}
public bool DeleteItem(int Id)
{
MyDataContext context = ContextHelper.GetContext();
ExampleAttribute a = (from m in context.ExampleAttributes
where m.Id == Id
select m).FirstOrDefault();
if (a == null)
return true;
// Make sure nothing is using it
int Count = (from m in context.Businesses
where m.ExampleAttributeId == a.Id
select m).Count();
if (Count > 0)
return false;
// Delete the item
context.ExampleAttributes.DeleteOnSubmit(a);
try
{
context.SubmitChanges();
return true;
}
catch
{
return false;
}
}
public bool UpdateItem(int Id, string Item, int SortOrder)
{
MyDataContext context = ContextHelper.GetContext();
ExampleAttribute a = (from m in context.ExampleAttributes
where m.Id == Id
select m).FirstOrDefault();
a.Name = Item;
a.SortOrder = SortOrder;
try
{
context.SubmitChanges();
return true;
}
catch
{
return false;
}
}
public String GetItem(int Id)
{
MyDataContext context = ContextHelper.GetContext();
var Attribute = (from a in context.ExampleAttributes
where a.Id == Id
select a).FirstOrDefault();
return Attribute.Name;
}
public Dictionary<int, string> GetItems()
{
Dictionary<int, string> Attributes = new Dictionary<int, string>();
MyDataContext context = ContextHelper.GetContext();
context.ObjectTrackingEnabled = false;
Attributes = (from o in context.ExampleAttributes orderby o.Name select new { o.Id, o.Name }).AsEnumerable().ToDictionary(k => k.Id, v => v.Name);
return Attributes;
}
#endregion
}
I could replicate this class 30 times with very minor changes for each lookup entity, but that seems messy somehow - so can this class be genericised so I can also pass it the type I want, and have it handle internally the type differences in the linq queries? That way, I have one class to make additions to, one class to bug fix et al - seems the way that it should be done.
UPDATE:
Andrews answer below gave me the option that I was really looking at while thinking about the question (passing the type in) but I need more clarification on how to genericise the linq queries. Can anyone clarify this?
Cheers
Moo
There are a couple things you can try.
One is to define an interface that has all the relevant fields that the thirty entity classes share. Then, you would be able to have each entity class implement this interface (let's call it IMyEntity) by doing something like
public partial class EntityNumber1 : IMyEntity
{
}
for each entity (where EntityNumber1 is the name of one of the entity classes). Granted, this is still thirty different definitions, but your CRUD operation class could then operate on IMyEntity instead of having to write a new class each time.
A second way to do this is simply to genericize the CRUD operation class, as you suggest:
public class ExampleAttributes<T> : IAttributeList
{
...
which allows you to use T as the type on which to operate. Granted, this might be easier in combination with the first method, since you would still have to check for the presence of the attributes and cast the entity to the appropriate type or interface.
Edit:
To check for the presence of the appropriate properties on the entity, you might need to use reflection methods. One way to check whether the given type T has a particular property might be to check for
typeof(T).GetProperties().OfType<PropertyInfo>().Count<PropertyInfo>(pi => pi.Name == "MyPropertyName" && pi.GetGetMethod().ReturnType == typeof(TypeIWant)) > 0
Of course, replace TypeIWant with the type you are expecting the property to be, and replace MyPropertyName with the name of the property for which you are checking.
Add a parameter to the constructors which specifies the type. Then you can work with it internally. One class, with perhaps a switch statement in the constructor.
For genericising a LINQ query, the biggest problem is that your DataContext has the collections based on type. There are a few ways this can be circumvented. You could try to access it using reflection, but that will require quite a bit of hacking and would pretty much destroy all efficiency that LINQ to SQL would provide.
The easiest way seems to be to use Dynamic LINQ. I have not used it personally, but it seems like it should support it. You can find more information in this thread: Generic LINQ query predicate?
and on http://aspalliance.com/1569_Dynamic_LINQ_Part_1_Using_the_LINQ_Dynamic_Query_Library.1
Maybe someone else can provide more information about this?
This isn't necessarily an answer to the question, but may be a solution to your problem. Have you considered generating all the classes that you need? T4 is built into Visual Studio, and can generate code for you. The link below describes it fairly broadly, but contains heaps of links for further information.
http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
That way, you can define all the methods in one place, and generate the class files for your 30-odd lookup models. One place to make changes etc.
Maybe worth considering, and if not, still worth knowing about.