2013-04-20 151 views
0

首先我想为混乱的标题道歉。我不太清楚如何将其写入文字,因此我将描述情况。某些泛型类的类属性强制转换为泛型类型来执行方法

我正在写一个比较引擎为我们的产品,也就是能够在不同的产品比较类似这样的:ComparableProduct,增加财产

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,如屏幕衍生

ComparableProperty<decimal> Dimension { get; set; } 

这意味着我可以有一个类的笔记本电脑,它有一个属性键盘,屏幕,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方法。预期的功能是在顶级类(比如Laptop)上通过其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; 

并改变吨至ComparableProperty和IEnumerable到IEnumerable的>整个比较完美的作品后,解决了这个。

回答

0

您可以创建一个非通用接口,然后用它的工作:

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(类型):像这样:

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); 
     } 
+0

哦,亲爱的,我没有睡觉时,我似乎失去了50%的智力。这的确是解决方案,谢谢! – NeroS 2013-04-20 19:56:50

+0

说得太快。编辑OP澄清。 – NeroS 2013-04-20 20:50:13

+0

对,答案在技术上仍然解决了我原来的问题,所以我会接受它。使用特定的界面做了这个窍门,但如果我想使用强大的打字功能,我仍然需要弄清楚它的一部分:) – NeroS 2013-04-21 00:38:23