C# covariant/contravariant 类型利用字典泛型
C# covariant/contravariant types utilizing generics with Dictionary
我需要帮助解决我的代码中的协变情况。
让我举例说明情况:
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
}
}
}
}
不久我需要不同类型映射器的字典,并在公共代码中使用它们的 Execute 方法来处理工作流。
你能指导我使用更好的代码或修复现有的解决方案吗?有可能吗?
或者我必须忘记这里的泛型并在 Map 方法中使用 BaseClasses 并将它们强制转换为我需要的类型。
像这样
abstract class BaseEntityMap : IEntityMapper
{
public abstract BaseTarget Map(BaseSource entity);
}
谢谢
您可以将 BaseEntityMap<TSource, TTarget>
class 中的通用约束应用于您的 BaseSource
和 BaseTarget
classes(或在 IEntityMapper<in TSource, out TTarget>
中应用约束接口并摆脱基础抽象 class)
abstract class BaseEntityMap<TSource, TTarget> : IEntityMapper<TSource, TTarget>
where TSource : BaseSource
where TTarget : BaseTarget
{
public abstract TTarget Map(TSource entity);
}
然后使用 Func<BaseSource, BaseTarget>
委托声明映射器字典,如下所示。它应该没问题,因为你已经约束了你的 BaseEntityMap<TSource, TTarget>
和 Func<in T, out TResult>
声明支持输入参数的逆变和结果的协方差
IDictionary<Type, Func<BaseSource, BaseTarget>> MappersMap = new Dictionary<Type, Func<BaseSource, BaseTarget>>();
public Workflow()
{
var orderMapper = new OrderEntityMapper();
MappersMap.Add(typeof(SourceEntityA), source => orderMapper.Map((SourceEntityA)source));
var goodsMapper = new GoodsEntityMapper();
MappersMap.Add(typeof(SourceEntityC), source => goodsMapper.Map((SourceEntityC)source));
//....more mappers
}
使用示例
foreach (var entity in entities)
{
var target = mapper(entity);
//.... code continues
}
我需要帮助解决我的代码中的协变情况。
让我举例说明情况:
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
}
}
}
}
不久我需要不同类型映射器的字典,并在公共代码中使用它们的 Execute 方法来处理工作流。
你能指导我使用更好的代码或修复现有的解决方案吗?有可能吗?
或者我必须忘记这里的泛型并在 Map 方法中使用 BaseClasses 并将它们强制转换为我需要的类型。
像这样
abstract class BaseEntityMap : IEntityMapper
{
public abstract BaseTarget Map(BaseSource entity);
}
谢谢
您可以将 BaseEntityMap<TSource, TTarget>
class 中的通用约束应用于您的 BaseSource
和 BaseTarget
classes(或在 IEntityMapper<in TSource, out TTarget>
中应用约束接口并摆脱基础抽象 class)
abstract class BaseEntityMap<TSource, TTarget> : IEntityMapper<TSource, TTarget>
where TSource : BaseSource
where TTarget : BaseTarget
{
public abstract TTarget Map(TSource entity);
}
然后使用 Func<BaseSource, BaseTarget>
委托声明映射器字典,如下所示。它应该没问题,因为你已经约束了你的 BaseEntityMap<TSource, TTarget>
和 Func<in T, out TResult>
声明支持输入参数的逆变和结果的协方差
IDictionary<Type, Func<BaseSource, BaseTarget>> MappersMap = new Dictionary<Type, Func<BaseSource, BaseTarget>>();
public Workflow()
{
var orderMapper = new OrderEntityMapper();
MappersMap.Add(typeof(SourceEntityA), source => orderMapper.Map((SourceEntityA)source));
var goodsMapper = new GoodsEntityMapper();
MappersMap.Add(typeof(SourceEntityC), source => goodsMapper.Map((SourceEntityC)source));
//....more mappers
}
使用示例
foreach (var entity in entities)
{
var target = mapper(entity);
//.... code continues
}