Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 如何创建可枚举<;Func<&燃气轮机&燃气轮机;方法外实例_C# 4.0_Reflection - Fatal编程技术网

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