C# 4.0 如何创建可枚举<;Func<&燃气轮机&燃气轮机;方法外实例
我正在创建一个看起来有点像单元测试框架的规则集引擎C# 4.0 如何创建可枚举<;Func<&燃气轮机&燃气轮机;方法外实例,c#-4.0,reflection,C# 4.0,Reflection,我正在创建一个看起来有点像单元测试框架的规则集引擎 [RuleSet(ContextA)] public class RuleSet1 { [Rule(TargetingA)] public Conclusion Rule1(SubjectA subject) { Create conclusion } [Rule(TargetingA)] public Conclusion Rule2(SubjectA subject) { Create co
[RuleSet(ContextA)]
public class RuleSet1
{
[Rule(TargetingA)]
public Conclusion Rule1(SubjectA subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
[RuleSet(ContextB)]
public class RuleSet2
{
[Rule(TargetingB)]
public Conclusion Rule1(SubjectB subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
public class Conclusion()
{
// Errorcode, Description and such
}
// contexts and targeting info are enums.
我们的目标是创建一个可扩展的规则集,该规则集不会改变消费者POV中的API,同时在代码文件中很好地分离关注点。再次强调:就像一个单元测试框架
[RuleSet(ContextA)]
public class RuleSet1
{
[Rule(TargetingA)]
public Conclusion Rule1(SubjectA subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
[RuleSet(ContextB)]
public class RuleSet2
{
[Rule(TargetingB)]
public Conclusion Rule1(SubjectB subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
public class Conclusion()
{
// Errorcode, Description and such
}
// contexts and targeting info are enums.
我正在尝试创建一个库来公开以下API
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets(contextFlags contexts)
{
{
return from type in Assembly.GetExecutingAssembly().GetTypes()
let attribute =
type.GetCustomAttributes(typeof (RuleSetAttribute), true)
.OfType<RuleSetAttribute>()
.FirstOrDefault()
where attribute != null
select ?? I don't know how to convert the individual methods to Func's.
}
}
}
internal interface IRuleset
{
IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; }
IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; }
}
另外,如果您能告诉我如何去掉“TargetingA”和“TargetingB”作为RuleAttribute参数,而是使用反射直接检查修饰方法的参数类型,那将非常有帮助。始终保持相同的简单外部API。在LINQ查询中,您直接前往
RuleSetAttribute
,因此丢失了其他信息。如果将查询拆分为几行代码,则可以使用从类型中获取方法,然后可以调用。您可以使用和方法执行所需操作
public class RuleSet : IRuleSet
{
public IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; set; }
public IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; set; }
}
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets() // removed contexts parameter for brevity
{
var result = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes(typeof(RuleSetAttribute), true).Any()
let m = t.GetMethods().Where(m => m.GetCustomAttributes(typeof(RuleAttribute)).Any()).ToArray()
select new RuleSet
{
SubjectARules = CreateFuncs<SubjectA>(m).ToList(),
SubjectBRules = CreateFuncs<SubjectB>(m).ToList()
};
return result;
}
}
// no error checking for brevity
// TODO: use better variable names
public static IEnumerable<Func<T, Conclusion>> CreateFuncs<T>(MethodInfo[] m)
{
return from x in m
where x.GetParameters()[0].ParameterType == typeof(T)
select (Func<T, Conclusion>)Delegate.CreateDelegate(typeof(Func<T, Conclusion>), null, x);
}
我仍然可以访问select语句中的“type”。它只是一个创建临时变量的“let”语句,而不是转换类型的“select”语句。顺便说一句:这不应该是一个评论,而不是一个答案吗?我相信我回答了主要问题,尽管我现在看到主要问题实际上并没有被问到。我认为主要的问题是如何收集所有方法的规则属性。不是吗?
var sa = new SubjectA();
foreach (var ruleset in RuleEngine.RuleSets())
{
foreach (var rule in ruleset.SubjectARules)
{
var conclusion = rule(sa);
// do something with conclusion
}
}