解决 C 语言中缺少 MI 的问题#

Working around missing MI in C#

提问人:sbi 提问时间:7/22/2010 更新时间:7/23/2010 访问量:170

问:

我有一些代码被传递到一个派生自某个类的类。我们称之为参数类。 该代码使用反射来遍历类的成员并分析提供给它们的某些自定义属性。
基本上,它是一个可配置的解析器,它将根据属性分析输入,并将其找到的内容放入数据成员中。

这在我们的代码中的几个地方使用。指定参数类,放入属性化数据成员,并将其传递给解析器。像这样的东西:

public class MyFancyParameters : ParametersBase
{
  [SomeAttribute(Name="blah", AnotherParam=true)]
  public string Blah { get; set; }

  // .. .more such stuff
}

var parameters = new MyFancyParameters();
Parser.Parse(input, parameters);

在许多地方,有类似的属性化数据成员组需要解析。因此,在某些地方,参数类是相似的。这是多余的,当然,这很痛苦。每当我需要在这样的区域进行更改时,我都需要在六个地方进行更改,所有地方都是克隆。这些部分开始分开只是时间问题。

但是,这些相似性不能在无环图中分组,因此我不能使用单继承来对它们进行分组。
我在 C++ 中要做的是将这些类似的东西块放入它们自己的类中,只需继承一堆包含我需要的任何内容的类,然后完成。(我认为这被称为混合继承。
但是,C# 没有多重继承。因此,我正在考虑将这些块放入数据成员中,并将解析器更改为递归为数据成员。但这会使解析器变得相当复杂。

还有什么?

c#

评论


答:

1赞 Dan Bryant 7/22/2010 #1

你能让你的解析器接受参数类的集合而不是单个参数类吗?或者,您可以允许解析器递归到参数类中,并让它提供其他参数类作为属性。基本上,继承自 ParametersBase 类型的 ParametersBase 派生类的每个属性都递归为单个参数列表,并平展为单个参数列表。

实际上,我刚刚看到您已经提到了递归解决方案。我认为这可能是你最好的选择,而且支持起来并不太复杂。您应该能够创建一个帮助程序函数,用于枚举参数属性,使层次结构看起来像平面类。


如果我正确理解您的要求,这里有一些代码可以提供您的属性的“扁平化”视图。您可能希望使用其他保护措施(例如保留一堆类型来检测循环引用)来扩充生产代码。

public class ParametersParser
{
    public static IEnumerable<PropertyInfo> GetAllParameterProperties(Type parameterType)
    {
        foreach (var property in parameterType.GetProperties())
        {
            if (Attribute.IsDefined(property, typeof(SomeAttribute)))
                yield return property;

            if (typeof(ParametersBase).IsAssignableFrom(property.PropertyType))
            {
                foreach (var subProperty in GetAllParameterProperties(property.PropertyType))
                    yield return subProperty;
            }
        }
    }
}

评论

0赞 sbi 7/23/2010
在我看来,更改解析器以递归方式分析参数类看起来比您想象的要困难,但这并非不可能。但是,我希望除了绕过语言限制之外,还有其他东西。难道我不能用接口做些什么聪明的事情吗?
0赞 Dan Bryant 7/23/2010
您可以将接口用于不同的参数“groups”,但在进行更改时,您仍然需要更改组的每次使用。使用接口的唯一优点是,如果您忘记修改其中一个组以匹配更新的接口,则会出现编译错误,但这也意味着您必须在另一个地方进行更改。
0赞 Dan Bryant 7/23/2010
进一步阅读,我可以看到您还需要跟踪对象值,这确实使它比简单地“展平”属性列表更复杂。也就是说,我想不出更好的解决方案。模拟 MI 的所有其他解决方法仍然需要编写样板来转发方法或属性,而这种重复的样板正是您要避免的。
0赞 sbi 7/23/2010
是的,我也需要存储对对象的引用,以便稍后为它们分配解析的值。正如我所说,这是可行的,但它只是一个拐杖,只需要解决缺失的语言功能。我仍然希望找到一个更好的主意来做到这一点。