同一列表中的多个泛型类型并调用它们的方法

问题描述:

我在业余时间制作一个对象验证框架来学习一些东西,并可能将它用于一些学校项目。同一列表中的多个泛型类型并调用它们的方法

我有我的通用规则类,它看起来是这样的:

class Rule<T> 
{ 
    string propertyName; 
    Func<T, bool> ruleLambda; 

    bool IsBroken(T value) 
    { 
     return ruleLambda(value); 
    } 
} 

将被验证看起来有点像这样的对象:

class Example 
{ 
    List<Rule<?>> MyRules; // can take all types of rules 

    List<Rule<T>> Validate<T>(string propertyName, T value) 
    { 
     List<Rule<T>> brokenRules = new List<Rule<T>>(); 
     foreach (Rule rule in MyRules.Where(r => r.propertyName == propertyName)) 
     { 
      if (rule.IsBroken(value)) 
       brokenRules.Add(rule); 
     } 
     return brokenRules; 
    } 
} 

T value论证会其中一个Example类的属性值,可以是任何类型的值。

只要设置了属性,就会调用Validate<T>方法。

问题在于班级的规则列表。具体是上面的List<Rule<?>>行。我想将给定类的所有规则存储在同一个列表中。

唉,C#没有像Java一样的泛型类型的通配符。

我该怎么做?

使用对象而不是T的非泛型接口或基类可以工作,但我该如何调用泛型规则的IsBroken方法而不是非泛型方法?

+4

定义一个接口IRule,带有非通用接口,例如'布尔IsBroken(物体)',并有'规则:IRule',并有'列表'..好吧,它不是很漂亮,但它*工作,是我见过的最好的。 – 2012-08-25 20:34:55

我已经尝试了一些东西,我发现一些作品非常好满足我的需求。我有一个抽象基规则类Rule<T>继承,与通用IsBroken方法:

abstract class Rule 
{ 
    string propertyName; 
    Func<object, bool> objectRule; 

    bool IsBroken<T>(T value) 
    { 
     Rule<T> rule = this as Rule<T>; 
     if (rule == null) 
      return objectRule(value); 

     return rule.IsBroken(value); 
    } 
} 

正如你所看到的,我尝试使用泛型类型参数在IsBroken方法对基类转换为它的通用同行。

此外,在创建一个Rule<T>实例时,我送一个Func<object, bool>其基类的受保护的构造:

public Rule(string propertyName, Func<T, bool> ruleLambda) 
    : base(propertyName, ConvertToObjectFunc(ruleLambda)) 
{ 
} 

与转换方法看起来像这样:

static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func) 
{ 
    return new Func<object, bool>(o => func((T)o)); 
} 

但是,如果它能够不会把o改成T型,它会崩溃。所以我写了这个......东西:

static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func) 
{ 
    return new Func<object, bool> 
    (
     o => 
     { 
      try 
      { 
       T obj = (T)o; 
       return func(obj); 
      } 
      catch { return true; } // rule is broken by default 
     } 
    ); 
} 

这是非常丑陋的,但它的作品。希望这可以帮助其他人。

在我需要类似这样的情况下,我使用接口或非泛型基类。例如,你可以创建一个接口:

public interface IRule 
{ 
    //non-generic properties & methods 
} 

public class Rule<T> : IRule 
{ 
    //implementation 
} 

然后创建接口的列表:

private List<IRule> MyRules; 

如果你想从接口转换成通用的方便,你可以添加一个扩展方法:

public static Rule<T> ToGeneric<T>(this IRule rule) 
{ 
    return rule as Rule<T>; 
} 

我会存储您的规则objectExample类中,并使用Enumerable.OfType<T>来找到一个给定的匹配规则类型:

class Example 
{ 
    private List<object> rules; 

    List<Rule<T>> Validate<T>(string propertyName, T value) 
    { 
     return this.rules.OfType<Rule<T>>() 
      .Where(r => r.PropertyName == propertyName && r.IsBroken(value)) 
      .ToList(); 
    } 
}