我正在构建一种库,用于根据某些规则在文档中执行文本替换。我们建立了一个POC,现在我正在尝试创建一个尽可能通用的库。
继承只有一个问题:
这是我正在处理的类/接口的简化表示:
public interface IRule {}
public interface IReplaceRule<T> : IRule
{
T ReplaceValue { get; set; }
}
public class CachedRules<T> where T : IReplaceRule<object>
{
#region Props
public T RuleTemplate { get; set; }
public IDictionary<string, T> RuleList { get; private set; } = null;
#endregion
public void SetRuleList(IDictionary<string, T> ruleList) { ... }
public bool ContainsRuleByKey(string key) { ... }
public bool TryGetRuleValueByKey(string key, out T rule) { ... }
}
public class SingleRowRule : IReplaceRule<string> { ... }
我还有一个类,类似于规则存储库,并且在其中可以根据需要添加任意数量的CachedRules
:
public class RulesStorage : AbstractRulesStorage
{
private CachedRules<SingleRowRule> singleRowRules;
public RulesStorage() { ... }
// Bunch of methods not useful for this question
// Here I need to return a list of ChachedRule, but just ofr testing I tried to return only one
public CachedRules<IReplaceRule<object>> GetCachedReplaceRules()
{
return singleRowRules;
}
}
在此类中,我需要一个方法来返回在CachedRules
中声明的所有RulesStorage
:
不幸的是RulesStorage.GetCachedReplaceRules
方法给我这个错误:
无法将类型
TestLib.Model.CachedRules<TestLib.Rules.SingleRowRule>
隐式转换为TestLib.Model.CachedRules<TestLib.Abstractions.IReplaceRule<object>
我真的不喜欢我必须放<object>
的事实,因为IReplaceRule
需要一个泛型,而且我被卡住了,因为我不知道如何返回此{{ 1}},而不会出现此编译错误。
你有什么主意吗?您认为我是否必须以不同的方式组织代码?
希望我已经说清楚了,谢谢!!
答案 0 :(得分:0)
您可以执行IReplaceRule<object>
从IEnumerable<T>
继承的方式来代替IEnumerable
。进行了这些细微调整之后,我创建了一个从T
到IReplaceRule
的隐式转换器,并且适当的约束现在可以确保我实际上可以安全地执行此操作。
我假设您有理由拥有private CachedRules<SingleRowRule> singleRowRules;
并且不能仅使用private CachedRules<IReplaceRule> singleRowRules;
来消除这种额外的转换跃迁。
public interface IReplaceRule : IRule { object ReplaceValue { get; set; } }
public interface IReplaceRule<T> : IReplaceRule { new T ReplaceValue { get; set; } }
public class CachedRules<T> where T : IReplaceRule
{
public IDictionary<string, T> RuleList { get; private set; } = new Dictionary<string, T>();
//The key ingredient for a nice experience instead of just doing this in the method
public static implicit operator CachedRules<IReplaceRule>(CachedRules<T> rules)
=> new CachedRules<IReplaceRule> { RuleList = rules.RuleList.ToDictionary(x => x.Key, x => x.Value as IReplaceRule) };
}
public class SingleRowRule : IReplaceRule<string>
{
public string ReplaceValue { get; set; }
object IReplaceRule.ReplaceValue { get => ReplaceValue; set => ReplaceValue = value as string; }
}
public class RulesStorage
{
private CachedRules<SingleRowRule> singleRowRules = new CachedRules<UserQuery.SingleRowRule>();
//FIXME: just for testing purposes
public RulesStorage() => singleRowRules.RuleList.Add("Hello", new SingleRowRule { ReplaceValue = "World" });
// Here I need to return a list of ChachedRule, but just ofr testing I tried to return only one
public CachedRules<IReplaceRule> GetCachedReplaceRules() => singleRowRules;
}