Inverting Interfaces Using Functional Programming

Every now and then I'll come across a problem that requires a bit of inside-out creativity. Let's pretend you are coding a CRM system that tracks a number of different types of entities.

public class CustomerDao
{
    public int CustomerId { get; set; }
    public int AddressId { get; set; }
}

public class VendorDao
{
    public int VendorId { get; set; }
    public int AddressId { get; set; }
}

public class AddressDao
{
    public int AddressId { get; set; }
    //Address stuff here
}

public class Customer
{
    public int CustomerId { get; set; }
    public Address Address { get; set; }
}

public class Vendor
{
    public int VendorId { get; set; }
    public Address Address { get; set; }
}

How can I write generic mapping code that will map either of those two object to their respective addresses?

Marking Compatible Types with Interfaces

The first thing you may have thought of would be to define an interface:

public interface IAddressableDao
{
    public int EntityId { get; set; }
    public int AddressId { get; set; }
}

public interface IAddressable
{
    public int EntityId { get; set; }
    public Address Address { get; set; }
}

Then you could easily write something simple to put these two things together and create a domain object:

public IEnumerable<T> MapAddresses<T>(IEnumerable<IAddressableDao> daos, IEnumerable<Address> addresses) where T : IAddressable, new()
{
    var addressMap = addresses.ToDictionary(x => x.AddressId);
    return daos.Select(x => new T 
    {
        EntityId = x.EntityId,
        Address = addressMap[x.AddressId]
    });
}

But what these are entities in an external dependency that you don't have control over?

Play Me That Sweet Func

There is another way to determine inside your mapping method how to get the various IDs from your data access objects: have the caller tell you how. By using a sprinkling of functional style programming, you can build a method that is just as generic, at a slight(!) cost to verbosity.

public IEnumerable<TDomain> MapAddresses<TDao, TDomain>(IEnumerable<TDao> daos, 
IEnumerable<Address> addresses, 
Func<TDao, int> addressIdSelector, 
Func<TDao, int> daoIdSelector, 
Action<TDomain, int> domainIdSetter, 
Action<TDomain, Address> domainAddressSetter)
{
    var addressMap = addresses.ToDictionary(x => x.AddressId);
    return daos.Select(dao =>
    {
        var address = addressMap[addressIdSelector(dao)];
        var domain = new TDomain();
        domainIdSetter(domain, daoIdSelector(dao));
        domainAddressSetter(domain, address);
        
        return domain;
    });
}

MapAddresses(daos, addresses, 
    x => x.AddressId, 
    x => x.VendorId, 
    (domain, id) => domain.VendorId = id, 
    (domain, address) => domain.Address = address);

This might be a bit of a silly example, but it does illustrate the interesting ways you can use functional programming to invert some code responsibilities in cases where you are unable to program to a specific interface.