-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Create objects with concrete classes & returning interfa
PostPosted: Thu May 15, 2008 11:06 am 
Newbie

Joined: Wed May 14, 2008 5:15 pm
Posts: 2
Hi.

As I'm new to NHibernate, please forgive me if this question has been answered before.

Here's my scenario:

I created a factory class that gets and saves objects using interfaces (e.g Load<T>(object id). Getting data by using the concrete class as the class name works. However, if I use the interface, I get a "No persister for: ...", which makes senses because the interface is not defined in the hbm.xml.

Also, I created the concrete class below that inherits from the interface below. While NHibernate has read-write access to the concrete class, I want it to return the read-only interface.

public interface IValueObject
{
int? Id { get; }
String Name { get; }
}

public class ValueObject : IValueObject
{
private int? _id;
private String _name;

public int? Id
{
get
{
return this._id;
}

set
{
this._id = value;
}
}

public String Name
{
get
{
return this._name;
}

set
{
this._name = value;
}
}
}

How do I configure the mapping file so that Nhibernate sets the fields in the concrete class, but casts objects to the interface?

I would appreciate if any help you can spare. If you know the answer, could you please reply or point me to the right resource or in the right direction?

Thanks.


Top
 Profile  
 
 Post subject: Create objects with concrete classes & returning interfa
PostPosted: Wed May 21, 2008 9:35 am 
Senior
Senior

Joined: Thu Jun 21, 2007 8:03 am
Posts: 127
Location: UK
Hi,

I don't think NHibernate can somehow automatically cast the return value to an interface for you. You could maybe do something clever with reflection to do that yourself though.

Is the reason for the interface to prevent clients using the public mutators? If so, another possibility is to simply mark them as protected (NHibernate proxies can still access them):

Code:
public String Name
{
    get { return this._name; }
    protected set { this._name = value; }
}


NHibernate can also access the fields directly when setting, allowing your class to have a read-only public property.

Regards,
Richard


Top
 Profile  
 
 Post subject: Re: Create objects with concrete classes & returning int
PostPosted: Wed May 21, 2008 11:08 am 
Newbie

Joined: Wed May 14, 2008 5:15 pm
Posts: 2
Hi.

Thanks for your reply! I have considered your suggesting about making a n object's mutators protected. However, I prefer to "program to an interface" because it's cleaner and will make my switch to lazy-loading with proxies easier.

Through some experimentation, I discovered that, in some cases, NHibernate actually does automatic casting for you. Let me explain. Let's say that you create a concrete class that implements an interface as I described before. Also, you've defined a mapping for a concrete class in an hbm.xml file.

Whenever you pass an interface to any session.Save, session.Update or session.Delete methods, NHibernate looks for the mapping that is the closest match. In this case, NHibernate will process these "interface" objects as if they were one of mapped concrete classes. I think that these methods actually look at the object's real type (concrete class) instead of the casted type (interface). I believe the documentation calls it implicit polymorphism.

The session.Load and session.Get methods fail using this approach. The "No persister for:" error would occur. So, I use the following workaround which allows you to query concrete classes as interfaces:

ICriteria searchCriteria = CreateSearchCriteria();

searchCriteria.Add(Expression.IdEq(id));
searchCriteria.SetCacheMode(CacheMode.Normal);
searchCriteria.SetCacheable(true);

DomainClass domainObject = searchCriteria.UniqueResult<DomainClass>();

where DomainClass can be an interface

Now NHibernate will treat interfaces as if they are mapped concrete classes.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.