We want to convert a List<Rule>
where we know they all derive from BuildingRule<T>
into BuildingRule<T>
, but the type T can be different.
We basically want to do
_buildingRules.Find(x => ((BuildingRule<T>)x).GetBuilding(sku, upgradeId) != null)
(the `.GetBuilding() != null is a requirement the rule has to meet in order for it to be the right one).
Though this does not work, and we were wondering if there is a way to achieve what we are trying to do.
public abstract class Rule
{
[XmlIgnore]
public abstract string FileName { get; }
}
public abstract class BuildingRule<T> : Rule where T : BuildingDefinitionRule
{
[XmlElement("Definition")]
public virtual List<T> Definitions { get; set; }
public virtual T GetBuilding(string sku, int upgradeId = 0)
{
return Definitions.Find(x => x.Sku == sku && x.UpgradeId == upgradeId);
}
}
public abstract class BuildingRule : BuildingRule<BuildingDefinitionRule>
{
}```
CodePudding user response:
You can create non-generic BuildingRuleBase
:
public abstract class BuildingRuleBase : Rule
{
public abstract BuildingDefinitionRule GetBuilding(string sku, int upgradeId = 0);
}
And inherit it:
public abstract class BuildingRule<T> : BuildingRuleBase where T : BuildingDefinitionRule
{
public override T GetBuilding(string sku, int upgradeId = 0)
{
return Definitions.Find(x => true);
}
}
And make _buildingRules
a collection of BuildingRuleBase
.
Or look into using covariant generic interfaces:
public interface IBuildingRule<out T> where T : BuildingDefinitionRule
{
T GetBuilding(string sku, int upgradeId = 0);
}
public abstract class BuildingRule<T> : Rule, IBuildingRule<T> where T : BuildingDefinitionRule
{
[XmlElement("Definition")]
public virtual List<T> Definitions { get; set; }
public T GetBuilding(string sku, int upgradeId = 0)
{
return Definitions.Find(x =>true);
}
}
With new List<IBuildingRule<BuildingDefinitionRule>>()
for type of _buildingRules
.