Domanda

I've created the following extension method:

public static T Map<TEntity,T>(this TEntity entity) where TEntity : IEntity
{
    return Mapper.Map<TEntity, T>(entity);        
}

This allows the following:

Db.ExchangeSets.FirstOrDefault().Map<ExchangeSet, ExchangeSetSimpleViewModel>()

However i'm wondering if there is anyway I can modify the extension method so i can call a shorted version as follows:

Db.ExchangeSets.FirstOrDefault().Map<ExchangeSetSimpleViewModel>()

Please Note:

Whether or not automapper should be used like this is not in the scope of the question, it's more a fact finding mission.


Update

For those of you playing at home, with the help of Scott's comment I managed to find an additional solution for the above function at Generic extension method for automapper.

public static T Map<T>(this IEntity entity) 
{
    return (T)Mapper.Map(entity, entity.GetType(), typeof(T));  
}
È stato utile?

Soluzione

In case you are wondering why this is just not possible, I'd think the problem lies with ambiguity:

public static T Map<TEntity,T>(this TEntity entity) where TEntity : IEntity
{
    return Mapper.Map<TEntity, T>(entity);        
}

public static T Map<T>(this ExchangeSet set)
{
    // ...
}

So, which method gets called? Keep in mind this is just a simple example. It's very well possible that there could be a future implementation of partial type inference, but I'd imagine it would be too confusing when it comes to overload resolution and the cost/benefit would be completely out of control. Then again, that's just speculation.

Altri suggerimenti

What you're asking for is not possible. When you call a generic method, either all generic type parameters must be inferable from the input or you must specify them all explicitly. Your method only has one input so you can't possibly infer two generic type parameters, thus they must always both be specified explicitly. Your suggested code implies that the method has only one generic type parameter, which would make it a different method.

If you introduce a second (chained) function call, you can achieve this:

Db.ExchangeSets.FirstOrDefault().Map().To<ExchangeSetSimpleViewModel>()

Inferred generic parameters is an all-or-nothing deal; if there aren't enough "actual" parameters passed into the method for the compiler to figure out the all of generic parameters, the compiler forces you to specify each generic parameters manually.

To be able to use the above snippet, you need to have one method call with one (the only) generic parameter inferred, and one method call with one manually specified generic parameter.

The To<> method can be implemented like this:

public static MapExtensionHelper<TEntity> Map<TEntity>(this TEntity entity) where TEntity : IEntity
{
    return new MapExtensionHelper<TEntity>(entity);        
}

public class MapExtensionHelper<TEntity> where TEntity : IEntity
{
    public MapExtensionHelper(TEntity entity)
    {
        _entity = entity;
    }

    private readonly TEntity _entity;

    public T To<T>()
    {
        return Mapper.Map<TEntity, T>(_entity);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top