How to create a Fluent Interface with Generics

c#, expression, fluent-interface, generics

Solution

You can achieve it with following code

static class ModelStateMappings
{
    public static DomainModelMapping<TDomainModel> MapDomainModel<TDomainModel>()
    {
        // edit the constructor to pass more information here if needed.
        return new DomainModelMapping<TDomainModel>();
    }
}

public class DomainModelMapping<TDomainModel>
{
    public ViewModelMapping<TDomainModel, TViewModel> MapViewModel<TViewModel>()
    {
        // edit the constructor to pass more information here if needed.
        return new ViewModelMapping<TDomainModel, TViewModel>();
    }
}

public class ViewModelMapping<TDomainModel, TViewModel>
{
    public ViewModelMapping<TDomainModel, TViewModel>
        Properties<TDomainPropertyType, TViewModelPropertyType>(
            Expression<Func<TDomainModel, TDomainPropertyType>> domainExpr,
            Expression<Func<TViewModel, TViewModelPropertyType>> viewModelExpr)
    {
        // map here
        return this;
    }
}

You don't have to specify all previously set generic types because they are already remembered as generic parameters of returned type. Generic parameters for `Properties` method call can be skipped because they will be inferred by compiler. And you get better typing than using `object`s everywhere.

Of course that's the simplest version. You can pass much more information between these types, because you specify how next necessary type is created.

It also make calling `MapViewModel` without calling `MapDomainModel` first impossible (as soon as you make the constructors `internal` and close everything in separate dll), what should be a good thing.

Problem

I wanted to create a fluent interface that can be used like so: ``` void Main() { ModelStateMappings.MapDomainModel<Book>().MapViewModel<BookViewModel>() .Properties(book => book.Author, vm => vm.AuthorsName) .Properties(book => book.Price, vm => vm.BookPrice); ModelStateMappings.MapDomainModel<Store>().MapViewModel<StoreViewModel>() .Properties(store => store.Owner, vm => vm.OwnersName) .Properties(store => store.Location, vm => vm.Location); } ``` I wanted end up with a collection that looked something like this: ``` static class ModelStateaMappings { private static IList<ModelMappings> mappings; // other methods in here to get it working } class ModelMappings { public Type DomainModelType {get;set;} public Type ViewModelType {get;set;} public IList<PropertyMapping> PropertyMappings {get;set;} } class PropertyMapping { public Expression<Func<object, object>> DomainProperty {get;set;} public Expression<Func<object, object>> ViewModelProperty {get;set;} } ``` I was not able to get the above accomplished but I did create something similar which works in a similar fashion but I don't particularly like how I had to setup the fluent interfaces. I would rather have it read like the way I have it above.

Original source