Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.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# 以类型安全的方式遍历对象层次结构_C#_Algorithm_Types - Fatal编程技术网

C# 以类型安全的方式遍历对象层次结构

C# 以类型安全的方式遍历对象层次结构,c#,algorithm,types,C#,Algorithm,Types,在工作中,我们有一个非常复杂的数据结构,t复杂: public class TComplex { public AType AType { get; set; } public BType BType { get; set; } public IList<CType> CTypes { get; set; } } public class AType { public int AInteger { get; set; } public int

在工作中,我们有一个非常复杂的数据结构,t复杂:

public class TComplex
{
    public AType AType { get; set; }
    public BType BType { get; set; }
    public IList<CType> CTypes { get; set; }
}

public class AType
{
    public int AInteger { get; set; }
    public int BInteger { get; set; }
    public string AString { get; set; }
}

public class BType
{
    public string AString { get; set; } 
    public IList<DType> DTypes { get; set; }
}

public class CType
{
    public int Id { get; set; }
    public string Value { get; set; }
}

public class DType 
{
    public string Value { get; set; }   
}
公共类TComplex
{
公共AType AType{get;set;}
公共b类型b类型{get;set;}
公共IList CTypes{get;set;}
}
公共类类型
{
公共int AInteger{get;set;}
public int BInteger{get;set;}
公共字符串AString{get;set;}
}
公共类B类型
{
公共字符串AString{get;set;}
公共IList数据类型{get;set;}
}
公共类CType
{
公共int Id{get;set;}
公共字符串值{get;set;}
}
公共类数据类型
{
公共字符串值{get;set;}
}
最近通过向多个节点类型添加enum ParsedValue对其进行了修改

public enum ParsedValue
{
    Parsed,
    Interpreted,
    Guessed,
    Explicit
}

public class TComplex
{
    public AType AType { get; set; }
    public BType BType { get; set; }
    public IList<CType> CTypes { get; set; }
}

public class AType
{
    public int AInteger { get; set; }
    public int BInteger { get; set; }
    public string AString { get; set; }
    public ParsedValue ParsedValue { get; set; }
}

public class BType
{
    public string AString { get; set; } 
    public IList<DType> DTypes { get; set; }
    public ParsedValue ParsedValue { get; set; }
}

public class CType
{
    public int Id { get; set; }
    public string Value { get; set; }
    public ParsedValue ParsedValue { get; set; }
}

public class DType 
{
    public string Value { get; set; }   
}
公共枚举解析值
{
解析,
解释,
猜猜看,
明确的
}
公共类TComplex
{
公共AType AType{get;set;}
公共b类型b类型{get;set;}
公共IList CTypes{get;set;}
}
公共类类型
{
公共int AInteger{get;set;}
public int BInteger{get;set;}
公共字符串AString{get;set;}
公共ParsedValue ParsedValue{get;set;}
}
公共类B类型
{
公共字符串AString{get;set;}
公共IList数据类型{get;set;}
公共ParsedValue ParsedValue{get;set;}
}
公共类CType
{
公共int Id{get;set;}
公共字符串值{get;set;}
公共ParsedValue ParsedValue{get;set;}
}
公共类数据类型
{
公共字符串值{get;set;}
}
首先,给定一个TComplex类型的对象,我如何遍历层次结构并生成ParsedValue的所有值:

public static IEnumerable<ParsedValue> GetParsedValues(TComplex tComplex)
公共静态IEnumerable GetParsedValue(TComplex TComplex)
更进一步,我如何才能将此对象中的所有ParsedValue设置为特定的ParsedValue,例如ParsedValue。显式:

public static IEnumerable<Action<ParsedValue>> SetParsedValues(TComplex tComplex)
公共静态IEnumerable setParsedValue(TComplex TComplex)
我有一个GetParsedValue和SetParsedValue的简单实现。但是,如果要向层次结构中的其他类型添加ParsedValue,则还需要更改GetParsedValue和SetParsedValue的实现,我发现这很脆弱:

public static IEnumerable<ParsedValue> GetParsedValues(TComplex tComplex)
{
    yield return tComplex.AType.ParsedValue;
    yield return tComplex.BType.ParsedValue;

    foreach(var cType in tComplex.CTypes)
    {
        yield return cType.ParsedValue;
    }
}

public static IEnumerable<Action<ParsedValue>> SetParsedValues(TComplex tComplex)
{
    yield return value => tComplex.AType.ParsedValue = value;
    yield return value => tComplex.BType.ParsedValue = value;

    foreach(var cType in tComplex.CTypes)
    {
        yield return value => cType.ParsedValue = value;
    }
}
公共静态IEnumerable GetParsedValue(TComplex TComplex)
{
返回tComplex.AType.ParsedValue;
返回tComplex.BType.ParsedValue;
foreach(tComplex.CTypes中的var cType)
{
返回cType.ParsedValue;
}
}
公共静态IEnumerable SetParsedValue(TComplex TComplex)
{
收益率返回值=>tComplex.AType.ParsedValue=value;
收益率返回值=>tComplex.BType.ParsedValue=value;
foreach(tComplex.CTypes中的var cType)
{
收益率返回值=>cType.ParsedValue=value;
}
}

我已经考虑过反射,但是有没有更好的方法呢?

要使它更通用,可以让每个类实现一个GetParsedValues和SetParsedValues函数,在复杂类型中,您现在可以依赖这些函数的实现,并确保它们返回您想要传递的内容

这里我只实现了GetParsedValues部分,同样的方法也可以应用于SetParsedValues

public class TComplex
{
    public AType AType { get; set; }
    public BType BType { get; set; }
    public IList<CType> CTypes { get; set; }
    public IEnumerable<ParsedValue> GetParsedValues()
    {
        foreach (var parsedValue in AType.GetParsedValues())
            yield return parsedValue;
        foreach (var parsedValue in BType.GetParsedValues())
            yield return parsedValue;

        foreach (var cType in CTypes)
            foreach (var parsedValue in cType.GetParsedValues())
                yield return parsedValue;
    }
}

public class AType
{
    public int AInteger { get; set; }
    public int BInteger { get; set; }
    public string AString { get; set; }
    public ParsedValue ParsedValue { get; set; }
    public IEnumerable<ParsedValue> GetParsedValues()
    {
        yield return ParsedValue;
    }
}

public class BType
{
    public string AString { get; set; } 
    public IList<DType> DTypes { get; set; }
    public ParsedValue ParsedValue { get; set; }
    public IEnumerable<ParsedValue> GetParsedValues()
    {
        yield return ParsedValue;
    }
}

public class CType
{
    public int Id { get; set; }
    public string Value { get; set; }
    public ParsedValue ParsedValue { get; set; }
    public IEnumerable<ParsedValue> GetParsedValues()
    {
        yield return ParsedValue;
    }
}
公共类TComplex
{
公共AType AType{get;set;}
公共b类型b类型{get;set;}
公共IList CTypes{get;set;}
公共IEnumerable GetParsedValues()
{
foreach(AType.GetParsedValues()中的var parsedValue)
收益率;收益率;
foreach(BType.getParsedValue()中的var parsedValue)
收益率;收益率;
foreach(CTypes中的变量cType)
foreach(cType.GetParsedValues()中的var parsedValue)
收益率;收益率;
}
}
公共类类型
{
公共int AInteger{get;set;}
public int BInteger{get;set;}
公共字符串AString{get;set;}
公共ParsedValue ParsedValue{get;set;}
公共IEnumerable GetParsedValues()
{
收益率;收益率;
}
}
公共类B类型
{
公共字符串AString{get;set;}
公共IList数据类型{get;set;}
公共ParsedValue ParsedValue{get;set;}
公共IEnumerable GetParsedValues()
{
收益率;收益率;
}
}
公共类CType
{
公共int Id{get;set;}
公共字符串值{get;set;}
公共ParsedValue ParsedValue{get;set;}
公共IEnumerable GetParsedValues()
{
收益率;收益率;
}
}

正如您所看到的那样,您可以修改您的类型,只需编辑该类型的函数。

我看不出您现在的操作方式有任何令人讨厌的地方,真的,但是如果您愿意,可以稍微清理一下

一种选择可能是为所有类编写一个公共基类
ParsedValueProviderBase
,而不是一个接口。为其提供两种相同方法的虚拟无操作实现:

public virtual IEnumerable<ParsedValue> GetParsedValues() 
    => Enumerable.Empty<ParsedValue>();

public virtual IEnumerable<ParsedValue> SetParsedValues(ParsedValue pv) 
    => Enumerable.Empty<ParsedValue>();
让每个人都实现这个接口。其中一些可能是这样的:

public IEnumerable<ParsedValue> GetParsedValues() 
    => yield return ParsedValue;

public IEnumerable<ParsedValue> SetParsedValues(ParsedValue pv) 
    => yield return ParsedValue = pv;
public IEnumerable GetParsedValues()
=>收益率返回解析值;
公共IEnumerable setParsedValue(ParsedValue pv)
=>收益率回报率ParsedValue=pv;
其他人会反复出现在孩子身上,等等


如果您可能在其他类中到处使用该接口,那么这可能是一个好主意。您可以编写接口并在
ParsedValueProviderBase
中实现它

Via reflection OP可以遍历所有属性并查找接口实现。:-)我喜欢这个主意。我能澄清一些事情吗?我是否应该考虑在层次结构中的每一个类型中实现iPaySturyValeType,并返回没有任何PARSEDIVE值的类型的枚举??(?),然后在添加了PARSEDIVE值之后修复实现?@ NVN911,这是一个判断调用。如果你认为有一个公平的机会,你以后会这样做,那么你可以像我们一样
public IEnumerable<ParsedValue> GetParsedValues() 
    => yield return ParsedValue;

public IEnumerable<ParsedValue> SetParsedValues(ParsedValue pv) 
    => yield return ParsedValue = pv;