某些泛型类型的类属性转换为泛型类型以执行方法
本文关键字:泛型类型 执行 转换 方法 属性 | 更新日期: 2023-09-27 18:10:05
首先我要为混乱的标题道歉。我不知道如何用语言表达,所以我将描述一下情况。
我正在为我们的产品编写一个比较引擎,它能够像这样比较不同的产品:
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; }
这意味着我可以有一个类Laptop,它有一个属性Keyboard, Screen, StorageDevice…等等,这些都是从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后,整个比较工作就完美了。
您可以创建一个非泛型接口,然后使用它:
public interface IComparableProperty
{
bool IsBetterThan(object target);
bool IsBetterThan(IEnumerable targets);
}
public abstract class ComparableProperty<T>: IComparableProperty 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;
}
bool IComparableProperty.IsBetterThan(object target)
{
return IsBetterThan((T) target);
}
bool IComparableProperty.IsBetterThan(IEnumerable targets)
{
return IsBetterThan((IEnumerable<T>) (targets));
}
}
编辑0:
您是否尝试像这样使用Type. isassignablefrom (Type)方法:
foreach (var property in GetType().GetProperties())
{
if (!typeof(IComparableProperty).IsAssignableFrom(property.PropertyType)) 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;
return local.IsBetterThan(compareTo);
}