I'm trying to write a Compare method to compare properties in some POCOs using Reflection to ensure that they've been persisted to the database correctly. For example, let's say I have this POCO:
public class NoahsArk
{
public string Owner { get; set; }
public ICollection<Animal> Animals { get; set; }
}
What I want to do is this:
[Test]
public class Saves_Correctly_To_Database()
{
var noahsArk = new NoahsArk { // some setup code here };
db.Save(noahsArk);
var dbNoahsArk = db.Get<NoahsArk>(noahsArk.Id);
Assert.That(Compare(noahsArk, dbNoahsArk), Is.True);
}
The ORM I'm using is NHibernate. My Compare method looks like this so far:
public static bool EqualsProperties<T>(this T x, T y)
{
var xType = x.GetType();
foreach (var property in xType.GetProperties())
{
if (property.GetValue(x, null).Implements(typeof(ICollection<>)))
{
var xValue = property.GetValue(x, null) as ICollection<T>;
var yValue = property.GetValue(y, null) as ICollection<T>;
}
Object.Implements() is an extension method I wrote to determine if a type implements an interface. As you can see, the method is incomplete. The problem I'm running into is that when I use property.GetValue(x, null), it returns an object, and I don't know how to cast it into its specific generic ICollection type. I need to be able to do this so I can use LINQ to do a x.Contains(y) to compare the two collections for equality. Any idea on how to do this?
P.S. I tried using Compare .NET Objects, but it's giving me a null reference exception somewhere deep within NHibernate. It doesn't properly handle how NHibernate proxies the ICollection for lazy loading. To make matters worse, NHibernate modifies the POCO to support lazy-loading, but this is all done at runtime. In the source code, it looks like you're just working with a regular ICollection, but NHibernate changes this to NHibernate.Collections.Generic.PersistentSet at runtime, and this is what's causing the comparer to fail.
Your question is a bit confusing because you don't need the type parameter T in the declaration of your EqualsProperties method. You just need
public static bool EqualsProperties(this object x, object y)
You then go on to use the same parameter T to cast properties of x and y to ICollection<T>; however, the objects in these collections obviously may have a different type than x and y.
Now to answer your question: you don't need to cast to the correct generic type to use the LINQ Contains method. You can do something like this:
xValue = property.GetValue(x, null);
yValue = property.GetValue(y, null);
if (typeof(IEnumerable).IsInstanceOf(x))
{
IEnumerable<object> xEnumerable = (x as IEnumerable).Cast<object>();
IEnumerable<object> yEnumerable = (y as IEnumerable).Cast<object>();
// use any LINQ method you like now
}
You should also make sure you use the LINQ overloads that take an equality comparer, as your domain objects obviously do not override the Equals method themselves. Otherwise you wouldn't be writing this unit testing code to compare them.
Sharp architecture framework use attribute to decor properties which should be taken into the equals method. See the source code of DomainSignatureAttribute class and EntityWithTypedId<>.Equals method.
Related
I have found myself cornered, so here we go.
Context
I need to produce a fingerprint hash code for object diffing. Comparing the hashes of two sets of objects will need to tell me if there are identical objects with the same hash.
The fingerprint hash must be platform-independent. So I went for MD5 hashing.
I am working with a large Object model code base that is out of my control. All types that I will be passed for this fingerprinting can not be modified by me. I cannot add attribute or constructors or modify anything. That does not exclude that the types will change in the future. So any approach must be programmatic -- I cannot just create a Surrogate class to avoid the problem; at least, not manually.
However, performance is not a concern, so reflection has complete green-light.
In addition, I will need to be able to control the exclusion of properties from the hashing. If I exclude a certain property, two object that have all the properties identical to each other except that one will still need to get the same hash.
Issue: serializing to Byte[] with hands tied on the legacy code
MD5 hashing requires the object to be Serialised in Byte[].
The serialisation requires the class to be marked as [Serializable]. Which I cannot add to the legacy code, and naturally it can not be added at runtime either.
So I went for protobuf-net.
Protobuf rightly fails when encountering types that implement an interface with Getter-only auto-properties:
public interface ISomeInterface
{
double Vpy { get; }
double Vy { get; }
double Vpz { get; }
...
}
Being this Interface implemented by many types, using Surrogates seems also a no-go (impractical, non maintainable).
I would just need to serialize, not to deserialize, so I don't see why the limitation of protobuf-net in this case. I understand protobuf-net would not be able to round-trip if needed, but I don't need to round-trip!
Question
Am I really cornered?
Is there any alternative?
My code
As I said, this works perfectly but only if the objects do not have any property (or nested property) that is a type with a Getter-only auto property.
public static byte[] ToByteArray(this object obj, List<PropertyInfo> exclusionsProps = null)
{
if (exclusionsProps == null)
exclusionsProps = new List<PropertyInfo>();
// Protobuf-net implementation
ProtoBuf.Meta.RuntimeTypeModel model = ProtoBuf.Meta.TypeModel.Create();
AddPropsToModel(model, obj.GetType(), exclusionsProps);
byte[] bytes;
using (var memoryStream = new MemoryStream())
{
model.Serialize(memoryStream, obj);
bytes = memoryStream.GetBuffer();
}
return bytes;
}
public static void AddPropsToModel(ProtoBuf.Meta.RuntimeTypeModel model, Type objType, List<PropertyInfo> exclusionsProps = null)
{
List<PropertyInfo> props = new List<PropertyInfo>();
if (exclusionsProps != null)
props.RemoveAll(pr => exclusionsProps.Exists(t => t.DeclaringType == pr.DeclaringType && t.Name == pr.Name));
props
.Where(prop => prop.PropertyType.IsClass || prop.PropertyType.IsInterface).ToList()
.ForEach(prop =>
{
AddPropsToModel(model, prop.PropertyType, exclusionsProps); //recursive call
}
);
var propsNames = props.Select(p => p.Name).OrderBy(name => name).ToList();
model.Add(objType, true).Add(propsNames.ToArray());
}
Which I will then use as such:
foreach (var obj in objs)
{
byte[] objByte = obj.ToByteArray(exclusionTypes);
using (MD5 md5Hash = MD5.Create())
{
string hash = GetMd5Hash(md5Hash, objByte);
Console.WriteLine(obj.GetType().Name + ": " + hash);
}
}
The simple solution here is to completely sidestep the root cause of your issue.
When you can't modify the existing classes, but you need some modifications for them, the easiest way to do that is to create a new and improved subclass, where the modifications you require are available.
Considering that the legacy codebase apparently will change outside of your control, the only way to deal with these changes is to generate these types at runtime. Luckily C# allows you to emit intermediate language which can solve exactly this problem.
You'd start with the DefineType method available from the ModuleBuilder class. Specifically you want to use the overload taking a String, TypeAttributes and a Type (representing the class you extend)
You pointed out that
If two objects have the same hash, you consider them exact copies of each other
Please realise that a hash has a finite entropy, while the source objects have infinite entropy. Hash collisions are bound to happen. Let's have a look at some examples:
public class Point
{
public int X;
public int Y;
}
public class Coordinate
{
public int X;
public int Y;
}
Let's say we calculate the hash as X ^ Y. Instances of both classes could have the same hash, even though they represent different classes. Even when taking just one of these classes, if we take one instance with X = 1, Y = 2 and the other X = 2, Y = 1, they have the same hash. Sure you could optimize the hash algorithm to mitigate the risk on collissions, but you cannot ensure that such collisions can be avoided at all time.
Instead, I would implement a DeepEquals method. This takes more effort (if writing it yourself). But when implemented correctly, it can ensure two objects to be copies.
I want to extend Linq's DataContext class to implement the ORM. Currently my model looks like this:
public class Trial : DataContext
{
public Trial(string connectionString) : base(connectionString) { }
[Column(DbType = "System.Guid", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public Guid TrialID { get; set; }
//...
}
However when I try to instantiate a new Trial object to insert it into the database I get an error complaining that Trial does not have a constructor that takes 0 arguments. When I try to create such a constructor, VS complains that DataContext does not have a constructor that takes 0 arguments.
Am I missing something here? How do I seperate the data context from the model definition?
(First time using Linq!)
Thanks in advance,
Max.
Your data context that represents the database view should inherit from DataContext. It should expose Tables where T is the entities (rows) that you want to add. Try generating a model from the database using the designer or SQLMetal and take a closer look at the generated code to see what's going on.
I am getting an error : i am using entity framework, wcf.
Error:cannot implicitly convert type System.linq.iorderedQueryable<xDataModel.Info> to System.Collection.Generic.List<xServiceLibrary.Info>
Below are my code:
WCF Service:
namespace xServiceLibrary
{
public List<Info> GetScenario()
{
xEntities db = new xEntities();
var query = from qinfo in db.Infoes
select qinfo;
//return query.Cast<Info>().ToList(); (not working)
//return query.toList(); (not working)
return query;
}
}
Interface:
namespace xServiceLibrary
{
[OperationContract]
List<Info> GetScenario();
}
Class:
namespace xServiceLibrary
{
[DataContract]
public class Info
{
[DataMember]
public int Scenario_Id;
[DataMember]
public string Scenario_Name { get; set; }
[DataMember]
public string Company_Name { get; set; }
}
}
update:(2)
I have two class library files.
One is xDataModel namespace in which i have created xmodel.edmx file.
second is xServiceLibrary namespace where i am implementing Wcf Service.
i have attached the xDataModel.dll file in my xServiceLibrary so that i could query my EF Model.
i am not able to understand the concept. any help would be appreciated.
The problem is that you have two different types named Info: DataModel.Info and ServiceLibrary.Info - because these are different types you cannot cast one into the other.
If there is no strong reason for both being there I would eliminate one of them. Otherwise as a workaround you could project DataModel.Info to ServiceLibrary.Info by copying the relevant properties one by one:
var results = (from qinfo in db.Infoes
select new ServiceLibrary.Info()
{
Scenario_Id = qinfo.Scenario_Id,
//and so on
}).ToList();
The problem is that you have two different classes, both called Info, both in scope at the time you run your query. This is a very very bad thing, especially if you thought they were the same class.
If DataModel.Info and ServiceLibrary.Info are the same class, you need to figure out why they are both in scope at the same time and fix that.
If they are different classes, you need to be explicit about which one you are trying to return. Assuming that your EF model includes a set of DataModel.Info objects, your options there are:
Return a List<DataModel.Info> which you can get by calling query.ToList()
Return a List<ServiceLibrary.Info> which you can get by copying the fields from your DataModel.Info objects:
var query = from qinfo in db.Info
select new ServiceLibrary.Info
{
Scenario_Id = q.Scenario_Id,
Scenario_Name = q.Scenario_Name
Company_Name = q.Company_Name
};
Return something else, such as your custom DTO object, similar to #2 but with only the specific fields you need (e.g. if ServiceLibrary.Info is a heavy object you don't want to pass around.
In general, though, your problem is centered around the fact that the compiler is interpreting List<Info> as List<ServiceLibrary.Info> and you probably don't want it to.
I have a base class DomainObject for all my business objects I am using with NHibernate. It contains the Id property.
public abstract class DomainObject
{
public virtual int Id { get; private set; }
}
I would like to write an IEqualityComparer to compare my domain objects. If two objects have the same Id and are the same kind of object they should be equal. However when I use GetType() to get the type of the object, it will return the NHibernate proxy type. So this code:
bool IEqualityComparer.Equals(object x, object y)
{
// null checking code skipped here
if(x is DomainObject && y is DomainObject)
{
return ((DomainObject) x).Id == ((DomainObject) y).Id
&& x.GetType() == y.GetType();
}
return x.Equals(y);
}
Doesn't work correctly, because the type of x is Asset but the type of y is AssetProxy21879bba3e9e47edbbdc2a546445c657.
So, how do I get the entity type on an object that may be a NHibernate proxy object? i.e. in the example above Asset instead of AssetProxy21879bba3e9e47edbbdc2a546445c657?
You can get the real type of a proxy with:
NHibernateUtil.GetClass(x);
or you can add a method to DomainObject like:
public virtual Type GetTypeUnproxied()
{
return GetType();
}
Which is really slick and doesn't depend directly on NHibernate.
Alternatively, one can approach the problem by saying you need to get the true object, rather than the proxy, which, if the session is handy, can be done with:
session.PersistenceContext.Unproxy(x);
As mentioned in another answer, if you're trying to implement equals it would be a good idea to check out the Sharp architecture implementation of Equals.
To get real object instead of proxy you can use
session.PersistenceContext.Unproxy(proxyObject)
But I think you should look at Sharp architecture implementation for Equals.
You can implement a backdoor property as described here to get the actual nonproxied instance.
i took a different aproach in a production project. I simply have a global HiLow Id-Generator which generates Id's unique for all types then i can:
// in DomainEntity
public override bool Equals(object obj)
{
var other = obj as DomainEntity;
if (Id == 0) // IsTransient()
return ReferenceEquals(this, other);
else
return (other != null) && (Id == other.Id);
}
// Comparer
bool IEqualityComparer.Equals(object x, object y)
{
return object.Equals(x, y);
}
Can a class return an object of itself.
In my example I have a class called "Change" which represents a change to the system, and I am wondering if it is in anyway against design principles to return an object of type Change or an ArrayList which is populated with all the recent Change objects.
Yes, a class can have a method that returns an instance of itself. This is quite a common scenario.
In C#, an example might be:
public class Change
{
public int ChangeID { get; set; }
private Change(int changeId)
{
ChangeID = changeId;
LoadFromDatabase();
}
private void LoadFromDatabase()
{
// TODO Perform Database load here.
}
public static Change GetChange(int changeId)
{
return new Change(changeId);
}
}
Yes it can. In fact, that's exactly what a singleton class does. The first time you call its class-level getInstance() method, it constructs an instance of itself and returns that. Then subsequent calls to getInstance() return the already-constructed instance.
Your particular case could use a similar method but you need some way of deciding the list of recent changes. As such it will need to maintain its own list of such changes. You could do this with a static array or list of the changes. Just be certain that the underlying information in the list doesn't disappear - this could happen in C++ (for example) if you maintained pointers to the objects and those objects were freed by your clients.
Less of an issue in an automatic garbage collection environment like Java since the object wouldn't disappear whilst there was still a reference to it.
However, you don't have to use this method. My preference with what you describe would be to have two clases, changelist and change. When you create an instance of the change class, pass a changelist object (null if you don't want it associated with a changelist) with the constructor and add the change to that list before returning it.
Alternatively, have a changelist method which creates a change itself and returns it, remembering the change for its own purposes.
Then you can query the changelist to get recent changes (however you define recent). That would be more flexible since it allows multiple lists.
You could even go overboard and allow a change to be associated with multiple changelists if so desired.
Another reason to return this is so that you can do function chaining:
class foo
{
private int x;
public foo()
{
this.x = 0;
}
public foo Add(int a)
{
this.x += a;
return this;
}
public foo Subtract(int a)
{
this.x -= a;
return this;
}
public int Value
{
get { return this.x; }
}
public static void Main()
{
foo f = new foo();
f.Add(10).Add(20).Subtract(1);
System.Console.WriteLine(f.Value);
}
}
$ ./foo.exe
29
There's a time and a place to do function chaining, and it's not "anytime and everywhere." But, LINQ is a good example of a place that hugely benefits from function chaining.
A class will often return an instance of itself from what is sometimes called a "factory" method. In Java or C++ (etc) this would usually be a public static method, e.g. you would call it directly on the class rather than on an instance of a class.
In your case, in Java, it might look something like this:
List<Change> changes = Change.getRecentChanges();
This assumes that the Change class itself knows how to track changes itself, rather than that job being the responsibility of some other object in the system.
A class can also return an instance of itself in the singleton pattern, where you want to ensure that only one instance of a class exists in the world:
Foo foo = Foo.getInstance();
The fluent interface methods work on the principal of returning an instance of itself, e.g.
StringBuilder sb = new StringBuilder("123");
sb.Append("456").Append("789");
You need to think about what you're trying to model. In your case, I would have a ChangeList class that contains one or more Change objects.
On the other hand, if you were modeling a hierarchical structure where a class can reference other instances of the class, then what you're doing makes sense. E.g. a tree node, which can contain other tree nodes.
Another common scenario is having the class implement a static method which returns an instance of it. That should be used when creating a new instance of the class.
I don't know of any design rule that says that's bad. So if in your model a single change can be composed of multiple changes go for it.