首先,我想为混乱的标题道歉。我不太清楚如何用语言表达,所以我将描述这种情况。
我正在为我们的产品编写一个比较引擎,它能够像这样比较不同的产品:
public abstract class ComparableProduct
{
public ComparableProperty<decimal> Weight { get; set; }
public ComparableProperty<decimal> Width { get; set; }
public ComparableProperty<decimal> Height { get; set; }
public ComparableProperty<decimal> Depth { get; set; }
public bool IsBetterThan(ComparableProduct target){}
}
实际产品派生自 ComparableProduct,如 Screen : ComparableProduct,增加了属性
ComparableProperty<decimal> Dimension { get; set; }
这意味着我可以拥有一个具有属性键盘、屏幕、存储设备...等的笔记本电脑类,它们都派生自 ComparableProduct。
它们又具有类似的属性,如下所示:
public abstract class ComparableProperty<T> where T : IComparable<T>
{
T Value { get; set; }
public ComparisonType ComparisonType { get; set; }
public bool IsBetterThan(T target)
{
if(ComparisonType == ComparisonType.GreaterThan)
return Value.CompareTo(target) >= 0;
return Value.CompareTo(target) <= 0;
}
public bool IsBetterThan(IEnumerable<T> targets)
{
foreach(var target in targets)
{
if (ComparisonType == ComparisonType.SmallerThan && Value.CompareTo(target) >= 0)
return false;
if (ComparisonType == ComparisonType.GreaterThan && Value.CompareTo(target) <= 0)
return false;
}
return true;
}
}
我还没有测试过这些,按照所有逻辑它们应该可以工作。我遇到的麻烦......是 ComparableProduct 中的 IsBetterThan 方法。预期的功能是,在顶级类(例如笔记本电脑)上,循环通过其 ComparableProduct 属性并为另一个副本调用 IsBetterThan,这些将循环通过它们的子属性......此外,所有 ComparableProduct ComparableProperty 属性都使用 IsBetterThan 检查与其他类的等效值。
无论如何,这就是我所拥有的,您可以立即看到我遇到的问题。
public bool IsBetterThan(ComparableProduct target)
{
foreach(var property in GetType().GetProperties().Where(x => x.PropertyType == typeof(ComparableProduct)))
{
var compareTo = target.GetType().GetProperty(property.Name).GetValue(target, null) as ComparableProduct;
var local = property.GetValue(this, null) as ComparableProduct;
if(local != null && !local.IsBetterThan(compareTo))
return false;
}
foreach(var property in GetType().GetProperties().Where(x => x.PropertyType == typeof(ComparableProperty<>)))
{
var compareTo = target.GetType().GetProperty(property.Name).GetValue(target, null) as ComparableProperty<>;
var local = property.GetValue(this, null) as ComparableProperty<>;
if(local != null && !local.IsBetterThan(compareTo))
return false;
}
}
如您所见,我试图将其转换为 ComparableProperty<>,这意味着它缺少泛型类型。但是,我不太确定如何获得所涉及属性的泛型。
另外,如果有更好的方法......我会尽我所能,但这是我想到的前半部分体面的方法。
编辑:
说得太早了。当我尝试像这样枚举 ComparableProduct 的 IsBetterThan 中的属性时:
foreach(var property in GetType().GetProperties())
{
var t = property.GetType().GetInterfaces();
if (!property.GetType().GetInterfaces().Contains(typeof(IComparableProperty))) continue;
var compareTo = target.GetType().GetProperty(property.Name).GetValue(target, null) as IComparableProperty;
var local = property.GetValue(this, null) as IComparableProperty;
if (local == null) continue;
if(!local.IsBetterThan(compareTo))
return false;
}
然后它似乎在接口中找不到 IComparableProperty。我已经浏览了可能包含它的主要方法......但它包含的唯一接口是 ICustomAttributeProvider、_MemberInfo、_PropertyInfo 和 ISerializable。
编辑2:
我已经通过回退字符串比较解决了这个问题
if (property.PropertyType.Name != "ComparableProperty`1") continue;
在将 T 更改为 ComparableProperty 并将 IEnumerable 更改为 IEnumerable> 之后,整个比较工作完美。