我有以下界面:
public interface IModel
{
ModelTypes ModelType { get; } // ModelTypes is an enum
}
public interface IModelConverter<T>
{
byte[] ToBytes(T model);
}
此外,我有IModel
的3个实现:ModelA
,ModelB
,ModelC
以及以下类:
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>
我知道这里的解决方案应该在T
IModelConverter
上使用协方差,因此应该是:
public interface IModelConverter<out T>
添加时,会出现以下错误:
参数必须是输入安全的。方差无效:类型参数&#39; T&#39; 必须在IModelConverter.ToBytes(T)上违反有效。 &#39; T&#39;是 协变。
有没有办法让它变得更好?我知道我可以制作每个ModelConverter
实现工具IModelConverter<IModel>
,但是在每次实现开始时我需要一个明显的演员。
答案 0 :(得分:7)
我知道这里的解决方案应该在
SELECT (p OR q OR r) AND (x OR y OR Z) AND (...)
T
上使用协方差
不,不是真的。只有当任何特定 IModelConverter
被视为更多一般 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
是正确的,那么应该没事。 (如果不是,一个例外可能是正确的行为。)
答案 1 :(得分:-1)
您可以明确键入强制转换以避免错误,如
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()}
};
}