将一般类委派给特定类



我有以下接口:

public interface IModel
{
ModelTypes ModelType { get; } // ModelTypes is an enum
}
public interface IModelConverter<T>
{
byte[] ToBytes(T model);
}

此外,我有IModel的3个实现:ModelAModelBModelC和以下类:

public class ModelAConverter : IModelConverter<ModelA>
public class ModelBConverter : IModelConverter<ModelB>
public class ModelCConverter : IModelConverter<ModelC>

我想取一个IModel,并用ToBytes方法进行转换。显然,我不想让调用者知道转换器的每一个实现,所以我创建了DelegatingConverter类:

public class DelegatingConverter : IModelConverter<IModel>
{
private readonly Dictionary<ModelTypes, IModelConverter<IModel>> _modelConverters;
public DelegatingConverter()
{
_modelConverters = new Dictionary<ModelTypes, IModelConverter<IModel>>
{
{ModelTypes.TypeA, new ModelAConverter()}, // Argument type ModelAConverter is not assignable to parameter type IModelConverter<IModel>
{ModelTypes.TypeB, new ModelBConverter()}, // Argument type ModelBConverter is not assignable to parameter type IModelConverter<IModel>
{ModelTypes.TypeC, new ModelCConverter()}  // Argument type ModelCConverter is not assignable to parameter type IModelConverter<IModel>
};
}
public byte[] ToBytes(IModel model)
{
// Here is the delegation..
return _modelConverters[model.ModelType].ToBytes(model);
}
}

一切都很顺利,直到我向委派字典_modelConverters添加了一些转换器。

错误为:

参数类型ModelXConverter不可分配给参数类型IModelConverter<IModel>

我知道这里的解决方案应该是在IModelConverter中使用T的协方差,所以偏差应该是:

public interface IModelConverter<out T>

当我添加它时,会出现以下错误:

参数必须输入安全。无效差异:类型参数"T"在IModelConverter上必须相反有效。ToBytes(T)。"T"为协变。

有什么方法可以让它变得更好吗?我知道我可以让每个ModelConverter实现实现IModelConverter<IModel>,但在每个实现的开头我都需要一个明显的强制转换。

我知道这里的解决方案应该是在IModelConverter中使用T的协方差

不,不是真的。只有当任何特定IModelConverter都可以被视为更通用的IModelConverter时,才会出现这种情况,但事实并非如此。如果转换器只知道如何将ModelB转换为字节,您希望它对ModelC做什么?

最简单的方法可能是写这样的东西:

// This class is general...
public sealed class DelegatingConverter<T> : IModelConverter<IModel>
where T : IModel
{
private readonly IModelConverter<T> originalConverter;
public DelegatingConverter(IModelConverter<T> originalConverter)
{
this.originalConverter = originalConverter;
}
public byte[] ToBytes(IModel model)
{
return originalConverter.ToBytes((T) model);
}
}

然后:

public sealed class KnownModelConverter : IModelConverter<IModel>
{
private static readonly Dictionary<ModelTypes, IModelConverter<IModel>>
= new Dictionary<ModelTypes, IModelConverter<IModel>>
{
{ ModelTypes.TypeA, new DelegatingConverter<ModelA>(new ModelAConverter()) },
{ ModelTypes.TypeB, new DelegatingConverter<ModelB>(new ModelBConverter()) },
{ ModelTypes.TypeC, new DelegatingConverter<ModelC>(new ModelCConverter()) },
};
public byte[] ToBytes(IModel model)
{
// Here is the delegation..
return _modelConverters[model.ModelType].ToBytes(model);
}
}

基本上,关键是DelegatingConverter<T>中的强制转换-您需要确保只使用正确类型的传递实例到其ToBytes方法-但假设model.ModelType是正确的,那应该没问题。(如果不是,例外可能是正确的行为。)

您可以显式键入强制转换以避免类似的错误

public DelegatingConverter()
{
_modelConverters = new Dictionary<ModelTypes, IModelConverter<IModel>>
{
{ModelTypes.TypeA, (IModelConverter<IModel>)new ModelAConverter()},
{ModelTypes.TypeB, (IModelConverter<IModel>)new ModelBConverter()},
{ModelTypes.TypeC, (IModelConverter<IModel>)new ModelCConverter()}
};
}

相关内容

  • 没有找到相关文章

最新更新