簡體   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