繁体   English   中英

我可以在公共API中为类重写ToString()吗?

[英]Can I override ToString() for classes in a public API?

我正在编写一个与另一软件的API接口的工具。 我的工具的一部分将需要生成有关通过API找到的各种对象的报告,并且我希望这些报告包含标识每个对象的简单字符串。 默认情况下,我计划使用ToString()为每个对象生成字符串。 但是,毫不奇怪,我发现此API中的默认ToString()实现不具有描述性。

最初,我考虑使用长的Switch语句执行类似以下代码的操作。 尽管这很可能会变得难以控制。

public string GetAPIObjectDescrition(object obj)
{
     Type t = obj.GetType();

     Switch(t)
     { 
         Case typeof(SomeAPIType):
             SomeAPIType x = (SomeAPIType)obj;
             return  x.SomeProperty;             


         Case typeof(SomeOtherAPIType):
             SomeOtherAPITypex = (SomeOtherAPIType)obj;
             return  x.SomeOtherProperty;

         default:
             return x.ToString();
     }
} 

接下来,我尝试使用扩展方法(请参见下面的代码)。 CustomObjectDescription()可以按预期工作,但是当我尝试调用ToString()时,它仅返回默认的ToString()结果。 我以前从未使用过扩展方法,因此我可能完全以为这样的想法是根本不可能的。

我不能保证API中遇到的每个Type都将有一个CustomObjectDescription()扩展,因此,如果我采用这种方法,我将不得不每次都不得不使用反射来检查当前对象是否具有GetObjectDescription()扩展。 。 我想尽可能避免使用反射。

public static class APIObjectDescriptionExtensions
{
    public static string ToString(this APIObject element)
    {
        return "ElementName = " + element.Name + " ElementID =" + element.Id.IntegerValue.ToString();
    }

    public static string CustomObjectDescription(this APIObject element)
    {
        return "ElementName = " + element.Name + " ElementID =" + element.Id.IntegerValue.ToString();
    }
}

有人对我应该如何解决此问题有其他建议吗? 我更喜欢一种解决方案,其中每种API类型的代码彼此独立(没有巨大的Switch语句)。

另外,如果可能的话,我希望一种类型的描述字符串代码可以继承到子类型,除非这些类型具有自己的唯一描述字符串代码。

我认为可能会有更好的解决方案,包括创建自定义TypeConverters或覆盖/扩展System.Convert.ToString()?


更新资料

我认为下面的示例可能有助于阐明我正在尝试做的事情。 最终,我希望能够从此API中获取任意类,并在运行时才知道其Type,然后生成描述字符串。 如果Type具有我的自定义扩展方法,则应使用它,否则代码应退回到普通的旧ToString()上。

    public static string GetDataDescription(object o)
    {
        //get the type of the input object
        Type objectType = o.GetType();

        //check to see if a description extension method is defined
        System.Reflection.MethodInfo extensionMethod = objectType.GetMethod("MyDescriptionExtensionMethod");

        if (extensionMethod != null)
        {
            //if a description extension method was found returt the result
            return (string)extensionMethod.Invoke(o, new object[] { });
        }
        else
        {
            //otherwise just use ToString();
            return o.ToString();
        }
    }

上面的这段代码不起作用,因为GetMethod()找不到扩展方法。

您可以为每个类提供一个包装,类似于以下内容:

    public class SomeAPITypeWrapper : SomeAPIType
    {
        public override string ToString()
        {
            return SomeProperty;
        }
    }

    public class SomeOtherAPITypeWrapper : SomeOtherAPIType
    {
        public override string ToString()
        {
            return SomeOtherProperty;
        }
    }

当然,这允许您在问题中使用基类/子类。 它还可以使它保持整洁,并保持在对象模型内部,而不是在switch语句或帮助器类中。

您可以将所有字符串拖延到应用程序的单独关注中。 StatePrinter( https://github.com/kbilsted/StatePrinter )是这样一种API,您可以在其中使用默认值或根据要打印的类型进行配置。

var car = new Car(new SteeringWheel(new FoamGrip("Plastic")));
car.Brand = "Toyota";

然后打印

StatePrinter printer = new StatePrinter();
Console.WriteLine(printer.PrintObject(car));

然后您得到以下输出

new Car() {
    StereoAmplifiers = null
    steeringWheel = new SteeringWheel()
    {
        Size = 3
        Grip = new FoamGrip()
        {
            Material = ""Plastic""
        }
        Weight = 525
    }
    Brand = ""Toyota"" }

使用IValueConverter抽象,可以定义打印机的类型,使用FieldHarvester,可以定义字符串中要包括的字段。

您是否在扩展类中尝试使用ToString()以外的其他名称? 我也不完全知道扩展方法,但是我猜是base.ToString被调用了而不是您的。 可能采用ToDescription()扩展方法会产生更好的结果。

如果给定的方法调用可以通过实例方法和扩展方法解决,则该实例方法将具有优先权。 因此,需要对扩展方法进行命名,以使其与扩展类型中的方法不具有相同的名称。

从上面的代码中,您似乎无法控制APIObject及其派生的来源。 因此,您可以选择“ 引入外部方法 ”和“ 引入本地扩展

  • 我会尝试外部方法(类似于C#扩展方法)..不确定为什么需要反射。 如果扩展方法不存在,则可能是编译时错误。 您如何使用这种方法?
  • 最后,switch语句还不错...除非它们很长/需要频繁更改/跨位置重复。

我建议制作一个Dictionary<Type,Converter<object,string>> 然后,您可以查找自定义的字符串生成器,如果找不到,则调用ToString

请注意,字典将检查类型是否完全匹配,因此,如果要处理子类,则必须编写一些其他代码以查看是否在字典中列出了基类型(提示:如果您匹配基类,或者即使您不这样做,也可以将实际的派生类型添加到字典中,这样就不必再次遍历继承树。

请注意,您可以为Object.ToString()建立一个符合Converter<object,string>协定的“开放委托”,并将其用作默认协定,甚至将其存储在字典中,而不是对ToString进行特殊处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM