C#协变/逆变类型使用带字典的泛型

C#协变/逆变类型使用带字典的泛型,c#,.net,generics,covariance,C#,.net,Generics,Covariance,我需要帮助解决代码中的协变情况 让我在示例中展示一下情况: abstract class BaseSource { } abstract class BaseTarget { } class SourceEntityA : BaseSource { } class TargetEntityB : BaseTarget { } interface IEntityMapper { } interface IEntityMapper<in TSource, out TTarget>:

我需要帮助解决代码中的协变情况

让我在示例中展示一下情况:

abstract class BaseSource { }
abstract class BaseTarget { }

class SourceEntityA : BaseSource { }
class TargetEntityB : BaseTarget { }

interface IEntityMapper { }
interface IEntityMapper<in TSource, out TTarget>: IEntityMapper
{
    TTarget Map(TSource entity);
}


abstract class BaseEntityMap<TSource, TTarget> : IEntityMapper<TSource, TTarget>, IEntityMapper
{
    public abstract TTarget Map(TSource entity);
}

class OrderEntityMapper : BaseEntityMap<SourceEntityA, TargetEntityB>
{
    public override TargetEntityB Map(SourceEntityA entity)
    {
        //do some map stuff
        return null;
    }
}

class GoodsEntityMapper : BaseEntityMap<SourceEntityC, TargetEntityD>
{
    public override TargetEntityD Map(SourceEntityC entity)
    {
        //do some map stuff
        return null;
    }
}

class Workflow
{
    IDictionary<Type, IEntityMapper> MappersMap = new Dictionary<Type, IEntityMapper>();
    public MappingArchestrator()
    {
        MappersMap.Add(typeof(SourceEntityA), new OrderEntityMapper());
        MappersMap.Add(typeof(SourceEntityC), new GoodsEntityMapper());
        //....more mappers
    }
    private IEnumerable<BaseSource> GetSourceEntities()
    {

        //return source data
        return null;
    }
    public void Execute()
    {
        foreach (var m in MappersMap.Keys)
        {
            var mapper = MappersMap[m];

            var entities = GetSourceEntities();

            foreach (var entity in entities)
            {
                //Need to handle this situations with correct covariations.
                var target = (IEntityMapper<BaseSource, BaseTarget>mapper).Map(entity);
                //.... code continues
            }
        }
    }
}

谢谢

您可以将
BaseEntityMap
类中的泛型约束应用于
BaseSource
BaseTarget
类(或者在
IEntityMapper
接口中应用约束并摆脱基本抽象类)

抽象类BaseEntityMap:IEntityMapper
其中TSource:BaseSource
其中TTarget:BaseTarget
{
公共抽象目标映射(TSource实体);
}
然后使用
Func
delegate声明映射器字典,如下所示。这应该没问题,因为您已经约束了
BaseEntityMap
,并且声明支持输入参数的逆变换和结果的协方差

IDictionary MapperMap=new Dictionary();
公共工作流()
{
var orderMapper=new OrderEntityMapper();
Add(typeof(SourceEntityA),source=>orderMapper.Map((SourceEntityA)source));
var goodsMapper=new GoodsEntityMapper();
Add(typeof(SourceEntityC),source=>goodsMapper.Map((SourceEntityC)source));
//……更多地图绘制者
}
用法示例

foreach(实体中的var实体)
{
var目标=映射器(实体);
//……代码继续
}

在我看来,您对泛型和接口的使用非常经典。你为什么对它不满意?问题是,我不能将映射器转换为var target=(IEntityMapper).Map(entity);。我需要强制转换它,因为我需要通用方法映射到performa实体映射。更清楚吗?实现
IEntityMapper
的类承诺将继承自
BaseSource
的任何类型的
TSource
作为输入。但是无论是
GoodsEntityMapper
还是
OrderEntityMapper
都无法做到这一点。@Glock它对您有帮助吗?你需要更多的细节或解释吗?你好,是的,这很有帮助。谢谢,我不想把它包装成代表:-)谢谢
abstract class BaseEntityMap : IEntityMapper
{
    public abstract BaseTarget Map(BaseSource entity);
}