[英]Class properties of certain generic type cast into generic type to execute methods
首先,我想为标题太乱表示歉意。 我不太确定如何把它写成文字,所以我将描述情况。
我正在为我们的产品编写一个比较引擎,该引擎能够比较不同的产品,例如:
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.