C# 自动遍历#

C# 自动遍历#,c#,C#,我需要做以下几点: 获取T类型的参数并将其设置为当前 检查(当前).Parent是否存在且类型为A,如果存在,请转到那里 检查(当前).Owner是否存在,是否为类型B,如果存在,请转到那里 检查是否存在(电流)。任何存在且属于C型的,如果存在,则前往那里 返回(当前) 这相当于 C c = ((param).Parent as A).Owner as B).Whatever as C; 使用一些安全性来检查是否有任何“步骤”为空 问题是,我想遍历完全不同的类型和完全不同的属性。我需要在我的结

我需要做以下几点:

  • 获取T类型的参数并将其设置为当前
  • 检查(当前).Parent是否存在且类型为A,如果存在,请转到那里
  • 检查(当前).Owner是否存在,是否为类型B,如果存在,请转到那里
  • 检查是否存在(电流)。任何存在且属于C型的,如果存在,则前往那里
  • 返回(当前)
  • 这相当于

    C c = ((param).Parent as A).Owner as B).Whatever as C;
    
    使用一些安全性来检查是否有任何“步骤”为空

    问题是,我想遍历完全不同的类型和完全不同的属性。我需要在我的结构中的几个不同的地方这样做。这可以通过某种方式实现自动化吗?也许可以使用lambdas、dynamics或某种泛型类?我在想这样的事情:

    C c = Util.Traverse<C>(someObj, new[]
    {
        new Step { Path = p => p.Parent, ExpectedType = typeof(A) },
        new Step { Path = p => p.Owner, ExpectedType = typeof(B) },
        new Step { Path = p => p.Whatever, ExpectedType = typeof(C) }
    });
    
    C=Util.Traverse(someObj,new[]
    {
    新步骤{Path=p=>p.Parent,ExpectedType=typeof(A)},
    新步骤{Path=p=>p.Owner,ExpectedType=typeof(B)},
    新步骤{Path=p=>p.Whatever,ExpectedType=typeof(C)}
    });
    
    空传播表达式(即,它的计算结果不是NRE,而是
    null
    )是被非正式地踢了几次的东西,但它只是不是C#中目前存在的一个特性

    没有一个好的方法来写这个。“丑陋的单一声明”的版本是:

    A a;
    B b;
    C c;
    // ...
    return (a = param.Parent as A) == null ? null :
           (b = a.Owner as B) == null ? null :
           (c = b.Whatever as C) == null ? null :
           // ...
           c.FinalThing;
    
    就我个人而言,我只是把它分成许多部分(可能是在助手方法中):


    空传播表达式(即,它的计算结果不是NRE,而是
    null
    )是被非正式地踢了几次的东西,但它根本不是C#中目前存在的特性

    没有一个好的方法来写这个。“丑陋的单一声明”的版本是:

    A a;
    B b;
    C c;
    // ...
    return (a = param.Parent as A) == null ? null :
           (b = a.Owner as B) == null ? null :
           (c = b.Whatever as C) == null ? null :
           // ...
           c.FinalThing;
    
    就我个人而言,我只是把它分成许多部分(可能是在助手方法中):


    我想你可以用lambdas来做这个

    Func<T, A> step1 = p => (p.Parent != null && p.Parent is A) ? p.Parent as A : null;
    Func<A, B> step2 = p => (p.Owner != null && p.Owner is B) ? p.Owner as B : null;
    Func<B, C> step3 = p => (p.Whatever != null && p.Whatever is C) ? p.Whatever as C : null;
    ...
    A a = step1(someObj) != null;
    B b;
    C c;
    if (a != null)
        b = step2(a);
    if (b != null)
        c = step3(b);
    return c;
    
    Func step1=p=>(p.Parent!=null&&p.Parent是A)?p、 父级为:null;
    Func step2=p=>(p.Owner!=null&&p.Owner是B)?p、 所有者为B:null;
    Func step3=p=>(p.Whatever!=null&&p.Whatever是C)?p、 C:null;
    ...
    A=步骤1(someObj)!=无效的
    B B;
    C C;
    如果(a!=null)
    b=步骤2(a);
    如果(b!=null)
    c=步骤3(b);
    返回c;
    
    我认为您可以使用lambdas来实现这一点

    Func<T, A> step1 = p => (p.Parent != null && p.Parent is A) ? p.Parent as A : null;
    Func<A, B> step2 = p => (p.Owner != null && p.Owner is B) ? p.Owner as B : null;
    Func<B, C> step3 = p => (p.Whatever != null && p.Whatever is C) ? p.Whatever as C : null;
    ...
    A a = step1(someObj) != null;
    B b;
    C c;
    if (a != null)
        b = step2(a);
    if (b != null)
        c = step3(b);
    return c;
    
    Func step1=p=>(p.Parent!=null&&p.Parent是A)?p、 父级为:null;
    Func step2=p=>(p.Owner!=null&&p.Owner是B)?p、 所有者为B:null;
    Func step3=p=>(p.Whatever!=null&&p.Whatever是C)?p、 C:null;
    ...
    A=步骤1(someObj)!=无效的
    B B;
    C C;
    如果(a!=null)
    b=步骤2(a);
    如果(b!=null)
    c=步骤3(b);
    返回c;
    
    如果您经常使用此方法,有时不得不使用自定义值而不是null,则可以编写如下扩展方法:

    public static class Helper
    {
        public static U SafeCast<T, U>(this T obj, Expression<Func<T, object>> memberExpression, U defaultValue)
            where T : class
            where U : class
        {
            if (obj == null)
            {
                return defaultValue;
            }
    
            var me = memberExpression.Body as MemberExpression;
            if (me == null)
            {
                throw new ArgumentException("memberExpression must be MemberExpression");
            }
    
            // TODO : Check for fields, not only properties
            var memberValue = obj.GetType().GetProperty(me.Member.Name).GetValue(obj) as U;
            if (memberValue != null)
            {
                return memberValue;
            }
    
            return defaultValue;
        }
    }
    

    如果您经常使用此方法,并且有时必须使用自定义值而不是null,则可以编写如下扩展方法:

    public static class Helper
    {
        public static U SafeCast<T, U>(this T obj, Expression<Func<T, object>> memberExpression, U defaultValue)
            where T : class
            where U : class
        {
            if (obj == null)
            {
                return defaultValue;
            }
    
            var me = memberExpression.Body as MemberExpression;
            if (me == null)
            {
                throw new ArgumentException("memberExpression must be MemberExpression");
            }
    
            // TODO : Check for fields, not only properties
            var memberValue = obj.GetType().GetProperty(me.Member.Name).GetValue(obj) as U;
            if (memberValue != null)
            {
                return memberValue;
            }
    
            return defaultValue;
        }
    }
    
    这个怎么样

    public static void CastAndContinue<T>(object toCast, Action<T> nextStep)
    {
      if (toCast is T)
        nextStep((T)toCast);
    }
    
    publicstaticvoidcastandcontinue(objecttocast,actionnextstep)
    {
    if(toCast是T)
    下一步((T)到cast);
    }
    
    援引为:

    //(param).Parent as A).Owner as B).Whatever as C
    finalThing localResult = null;
    CastAndContinue<A>(param.Parent, 
        p => CastAndContinue<B>(p.Owner, 
        x => CastAndContinue<C>(x.Whatever, z=> finalThing = z)
    
    //(param)。父对象为A。所有者为B)。任意值为C
    finalThing localResult=null;
    CastAndContinue(参数Parent,
    p=>CastAndContinue(p.Owner,
    x=>CastAndContinue(x.Whatever,z=>finalThing=z)
    
    这个怎么样

    public static void CastAndContinue<T>(object toCast, Action<T> nextStep)
    {
      if (toCast is T)
        nextStep((T)toCast);
    }
    
    publicstaticvoidcastandcontinue(objecttocast,actionnextstep)
    {
    if(toCast是T)
    下一步((T)到cast);
    }
    
    援引为:

    //(param).Parent as A).Owner as B).Whatever as C
    finalThing localResult = null;
    CastAndContinue<A>(param.Parent, 
        p => CastAndContinue<B>(p.Owner, 
        x => CastAndContinue<C>(x.Whatever, z=> finalThing = z)
    
    //(param)。父对象为A。所有者为B)。任意值为C
    finalThing localResult=null;
    CastAndContinue(参数Parent,
    p=>CastAndContinue(p.Owner,
    x=>CastAndContinue(x.Whatever,z=>finalThing=z)
    
    在您的指导下,我编写了两种不同的解决方案:

    使用动态和lambdas:
    在您的指导下,我编写了两种不同的解决方案:

    使用动态和lambdas:
    请注意,我使用了你们所有的解决方案来构建我的解决方案,但我无法将所有解决方案标记为已回答。因此,我选择了一个目前得分最少的解决方案。谢谢大家!请注意,我使用了你们所有的解决方案来构建我的解决方案,但我无法将所有解决方案标记为已回答。因此,我选择了一个目前得分最少的解决方案。谢谢大家!另一个有趣的方法是“maybe monad”。参见另一个有趣的方法是“maybe monad”。参见
    C c = obj.Traverse(p => p.Parent as A)
        .Traverse(p => p.Owner as B)
        .Traverse(p => p.Whatever as C);