2016-09-16 14 views
4

我正在编写一个php服务和我们的crm之间的互操作。我需要做的事情之一是确保简单的类型转换为ToString()以供稍后在json转换器中使用。如何确定对象是否可以将ToString转换为值或键入名称?

我不确定'简单类型'的名称是什么,但它可以像这样定义...“表示低级变量类型的对象,包含单个值,不包含类或任何可执行函数等“

我发现INT,字符串,布尔,双和令人惊讶的枚举将ToString()与相当可预测的结果。

int x = 0; 
bool y = true; 
double z = 1.59 // money 
CustomEnum theEnum = CustomEnum.somevalue; 

x.ToString()的结果为 “0”

y.ToString()的结果为 “真”

z.ToString()的结果为 “1.59”

theEnum的ToString()导致 “someValue中”

但是,如果我用这个:

List<int> iList = new List<int>(); 
iList.Add(1); 

MyClass theClass = new MyClass(); 

iList.ToString()的结果为 “System.Collections.Generic.List`1 [System.Int32]” theClass.ToString()的结果为 “STTI.NKI.Interop.MyClass”

我不限于列表。我可以有一个ExpandoObject或一个类等

我明白为什么发生这种情况,我想知道是否有一种快速方法来确定未知类型的对象是否将ToString()转换为预期值,而不是类型名称。我发现这是一个反模式做这样的事情

switch (theObject.GetType()) 
case typeof(int): 
case typeof(bool): 
case typeof(doulble): 
etc 

我不知道该条款是什么,所以谷歌上搜索我的答案被证明是困难的。

+0

如果列表,使用的string.join(“” myList中)得到的CSV字符串所有值 –

+0

结果始终是一个字符串,那么如何获得一个值? (除了使用'string.ToString') – leppie

+3

如果你在控制你的服务/接口将要公开的类型,你可以确保每个暴露的对象都覆盖了ToString(),使得它呈现一个可读的表示的内容。 @leppie如果我知道它是正确的,OP想知道是否有可能检查类型是否它的ToString()覆盖(或基类默认)将呈现对象内容的要点或其类型的表示/ generic – dlatikay

回答

2

所以,你要检查类型是否具有重写ToString方法?为什么不检查ToString返回的值是否等于默认实现ToString返回的值?

here,我们知道的ToString的默认实现

return GetType().ToString(); 

所以,我们可以用它来检查对象是否已经覆盖了ToString方法:

bool toStringOverridden = someObject.GetType().ToString() != 
    someObject.ToString(); 
+0

这是一个很好的技巧,我可以用它来做比较。要么返回myobject.ToString()如果ToString!=输入名称,如果相等,则抛出错误。从技术角度来看,这也是正确的答案,因为我要求一种方法来做到这一点。你的真实/错误解决方案与我的问题最匹配,尽管这里有许多好的答案,还有很多很棒的信息。 – CarComp

0

选项1:确保每个对象都会覆盖ToString()。 选项2:使用反射来获取所有对象属性并将它们连接。

0

也许你可以做同样的事情到这一点:

bool ToStringIsTyped<T>(T myObj) 
{ 
    return myObj.ToString().Contains(typeof(T).FullName); 
} 

它可能无法适用于所有情况,但可能可以扩大

0

我认为这是你在看什么,在GetMethod中,第二个参数是一个空数组来监视。ToString(),只需将i.GetType().GetMethod("ToString", new Type[] { }).DeclaringType == typeof(object)转换为函数,然后就可以了。

class Program 
    { 
     static void Main(string[] args) 
     { 
      int i = 55; 
      var s = "some string"; 
      var x = new List<string>(); 
      Console.WriteLine(i.ToString()); 
      Console.WriteLine(i.GetType().GetMethod("ToString", new Type[] { }).DeclaringType == typeof(object)); 
      Console.WriteLine(s.ToString()); 
      Console.WriteLine(s.GetType().GetMethod("ToString",new Type[]{}).DeclaringType == typeof(object)); 
      Console.WriteLine(x.ToString()); 
      Console.WriteLine(x.GetType().GetMethod("ToString",new Type[]{}).DeclaringType == typeof(object)); 
     } 
    } 
2

ToString方法是一个虚拟的和缺省的实现是在Object类中定义并简单地返回对象的类型的名称:

public virtual string ToString() 
{ 
    return this.GetType().ToString(); 
} 

int例如,覆盖此方法返回有意义的表示。

你可以做的是使用反射来检测类型是否覆盖ToString方法是这样的:

public static bool OverridesToString(Type type) 
{ 
    return type.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object); 
} 

如果是这样,有一个很好的机会,ToString方法将返回有意义的事。

+1

将'obj.ToString()'与'obj.GetType()进行比较不是更有用吗?ToString()'?即使对象覆盖'ToString',它仍然可以返回类型名称。 – Sweeper

+0

@Sweeper,为什么有人会重写'ToString'来返回类型的名字?这些方法都是启发式的。如果有人返回一个随机字符串呢?还是非完整的名称? –

0

...方法来确定是否按照未知类型的对象会的ToString()为预期值,而不是类型名称...

object默认实现的ToString(),到documentation,返回“对象类型的完全限定名称”。因此,我们可以提出一个假设,即每当ToString()被覆盖时,其输出将在问题中指定的意义上是“有用的”。

要检测一个调用的函数是一个覆盖,我们可以利用的this answer,就像这样:

if(typeof(ObjectX).GetMethod("ToString").DeclaringType == typeof(ObjectX)) 
{ 
    /* ObjectX has overridden ToString() */ 
} 
else 
{ 
    /* ObjectX has inherited ToString() from its base class(es) */ 
} 
+0

使用此代码获取大量AmbiguousMatchExceptions。我认为它需要新的Type [0]部分才能正常工作。括号也不完全正确。 – CarComp