Nathan Raley
Nathan Raley

Reputation: 485

Fluent NHibernate automapping

I was just wandering if it would be possible to use the Fluent NHibernate to auto map a .Net TcpClient object?

I have a class that has a TcpClient property which I would like to map.

I tried creating a custom class inheriting from TcpClient called tTcpClient and adding an Id Property with a getter/setter; however, it was still looking for the Id field for the base class.

Anyone have any ideas if it is possible, or will I need to create my own xml mapping for the TcpClient?

I was sort of hoping to be able to save the object to easily recreate it on reloading the application and to bind the properties of the TcpClient object to the PropertiesGrid and allowing configuration through that rather easy.

Thanks.

Upvotes: 1

Views: 757

Answers (2)

Dmitry
Dmitry

Reputation: 17350

NHibernate does not know how to deal with complex types like TcpClient out of the box. But it lets you provide your own loading and storing code. You can use IUserType:

public class TcpClientMapper : IUserType {

    public SqlType[] SqlTypes {
        get {
            return new[] { 
                           new SqlType(DbType.String), 
                           new SqlType(DbType.Int32) 
                         };
        }
    }

    public Object NullSafeGet(IDataReader rs, String[] names, ...) {

        String address = NHibernateUtil.String.NullSafeGet(rs, names[0]);
        Int32 port = NHibernateUtil.Int32.NullSafeGet(rs, names[1]);

        return new TcpClient(address, port);
    }

    public void NullSafeSet(IDbCommand cmd, Object value, Int32 index) {
        TcpClient tcpClient = value as TcpClient;
        if(tcpClient == null) {
            NHibernateUtil.String.NullSafeSet(cmd, null, index);
            NHibernateUtil.Int32.NullSafeSet(cmd, null, index + 1);
        } else {
            EndPoint red = tcpClient.Client.RemoteEndPoint;
            IPEndPoint endpoint = ((IPEndPoint)red);
            NHibernateUtil.String.Set(cmd, endpoint.Address.ToString(), index);
            NHibernateUtil.Int32.Set(cmd, endpoint.Port, index + 1);
        }
    }

    public Type ReturnedType {
        get { return typeof(TcpClient); }
    }

    // TODO: implement other methods
}

And map it like this in hbm:

<property name="_tcpClient" type="MyNamespace.TcpClientMapper, MyAssembly">
    <column name="Address" />  <!-- NullSafeGet/Set index == 0 -->
    <column name="Port" />     <!-- NullSafeGet/Set index == 1 -->
</property>

Or use fluent UserTypeConvention:

public class TcpClientUserTypeConvention : UserTypeConvention<TcpClientMapper> {
}

Upvotes: 2

Iain
Iain

Reputation: 6452

Nathan,

Have you had a look at this project?

http://automapper.org/

Cheers

Upvotes: 1

Related Questions