I depends where you have to pass your result to. Is it in the same process, say in the server, you don't need any special class, because you can make use of lazy loading. You configure NHibernate to only load referenced entities when you access them.
If you send the result over the wire, it is different, because you need to serialize the data and need all properties to be complete. This is actually not a problem of NHibernate, it is a problem of your server interface. Then you need a special DTO (data transfer object) that includes only the data that is needed on the client.
Edit:
I think what you need is lazy loading. There are two different kinds of lazy loading. Lazy loading of collections and lazy loading of references to single entities.
Example:
class Employee
{
// make everything virtual to allow NH to build a proxy
public virtual string name { get; set; }
// will be lazy loaded
public virtual IList<Customers> Customers { get; private set; }
public virtual Employee Boss { get; set; }
}
Mapping
<!-- lazy=true is actually default -->
<class name="Employee" lazy="true">
<property name="Name"/>
<property name="Boss"/>
<!-- lazy=true is actually default -->
<bag name="Customers" type="Employee" lazy="true">
<key column="Employee_FK"/>
<one-to-many class="Employee" />
</bag>
</class>
Example Code
using (ISession session = CreateSession())
using (ITransaction trx session.CreateTransaction())
{
// get a instance of an employee
// the boss and the customers are not loaded until now
Employee emp = session.Get<Employee>(empid);
// emp.Boss is a proxy. This is a subclass of employee
// generated by NH that implements the lazy loading
// this loads the boss' data
if (emp.Boss.Name == "gogogurt")
{
// this is your employee
}
// this loads the Customers
if (emp.Customers.Count == 0)
{
HumanResources.Fire(emp);
}
trx.Commit();
}
// outside the session you cannot access the lazy
// loaded properties.