同一列表中的多个泛型类型并调用其方法(Multiple generic types in same list and calling their methods)

编程入门 行业动态 更新时间:2024-10-26 00:29:57
同一列表中的多个泛型类型并调用其方法(Multiple generic types in same list and calling their methods)

我在业余时间制作一个对象验证框架,以学习一些东西,并可能将它用于一些学校项目。

我有我的通用Rule类,它看起来像这样:

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方法而不是非泛型方法呢?

I'm making an object validation framework in my spare time to learn a few things and maybe use it for some school projects.

I have my generic Rule class, which looks something like this :

class Rule<T> { string propertyName; Func<T, bool> ruleLambda; bool IsBroken(T value) { return ruleLambda(value); } }

An object that would be validated would look a bit like this :

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; } }

Where the T value argument would be the value of one of the Example class's properties, which can be of any type.

The Validate<T> method is called whenever a property is set.

The problem lies with the class's list of rules. Specifically the List<Rule<?>> line above. I want to store all the rules for a given class in the same list.

Alas, C# doesn't have a wildcard for generic types like in Java.

How should I do this?

A non-generic interface or base class utilizing objects instead of T could work, but how would I call the generic Rule's IsBroken method and not the non-generic one?

最满意答案

我将您的规则作为object存储在Example类中,并使用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(); } }

I've tried a few things and I've found something that works pretty well for my needs. I have Rule<T> inherit from a base abstract rule class, with a generic IsBroken method:

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

As you can see, I try to convert the base class to its generic counterpart using the generic type parameter in the IsBroken method.

Also, when creating a Rule<T> instance, I send a Func<object, bool> to its base class protected constructor:

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

With the conversion method looking like this:

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

However, if it can't cast o to type T, it crashes. So I wrote this... thing:

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

It's pretty ugly, but it works. Hope this can help anybody else.

更多推荐

本文发布于:2023-08-07 03:56:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1460042.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多个   类型   方法   列表中   Multiple

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!