2016-12-07 2 views
2

XAttribute и XElement оба происходят от XObject.Можно ли написать метод для XAttribute И XElement?

Оба имеют собственность Value.

До сих пор, это то, что я придумал, чтобы делать то, что я хочу:

string FooMyXObject(XObject bar){ 
    if (bar.NodeType == NodeType.Element) 
     return (bar as XElement).Value; 
    else if (bar.NodeType == NodeType.XAttribute) 
     return (bar as XAttribute).Value; 
    else 
     throw new Exception("Generic Fail Message"); 
} 

Это чувствует себя неуклюжим. Я надеюсь, что есть способ сделать это менее неуклюжим. Некоторый способ доступа к свойству Value из XObject, так как они оба имеют имена свойств строки Value.

Возможно ли это, или я просто вынужден сделать это таким неуклюжим способом?

+1

['XText'] (https://msdn.microsoft.com/en-us/library/system.xml.linq.xtext (v = vs.110) .aspx) и [' XComment'] (https : //msdn.microsoft.com/en-us/library/system.xml.linq.xcomment (v = vs.110) .aspx) также имеют свойство «Значение» без базового базового класса. На самом деле это немного раздражает. Это именно та ситуация, когда интерфейс «IHasValue» был бы уместным. – dbc

ответ

2

Вы можете бросить bar в dynamic, чтобы избежать отдельных ветвей:

string FooMyXObject(XObject bar){ 
    if (bar.NodeType == NodeType.Element || bar.NodeType == NodeType.XAttribute) 
     return ((dynamic)bar).Value; 
    else 
     throw new Exception("Generic Fail Message"); 
} 
+0

Мне это нравится. Это, безусловно, лучше, чем то, что я делал (и метод GetType() .GetProperty («Value») .GetValue (Bar) .ToString() '). – Will

+0

При использовании 'dynamic', появляется эффект производительности. Код, предоставленный OP в его вопросе, будет вести себя лучше с точки зрения производительности, и я предложил использовать его вместо этого. – MarcinJuraszek

2

Если свойство .Value определено в XObject, тогда вы можете написать это довольно просто, используя generics.

т.е.

string FooMyXObject<T>(T bar) where T : XObject 
{ 
    return bar.Value; 
} 

Если это не так, то вам следует рассмотреть вопрос о переходе его к базовому классу, если она является общей функциональности производных классов.

Редактировать: Ваш код в значительной степени прав, если это свойство Value не относится к базовому классу. Может быть, вы могли бы реорганизовать его, как это, используя случай для более легкого расширения:

string FooMyXObject(XObject bar) 
{ 
    switch(bar.NodeType) 
    { 
     case NodeType.Element: 
      return (bar as XElement).Value; 
     case NodeType.XAttribute: 
      return (bar as XAttribute).Value; 
     default: 
      throw new Exception("Generic Fail Message"); 
    } 
} 

или просто для удовольствия

string FooMyXObject(XObject bar) 
    { 
     try 
     { 
      dynamic temp = bar; 
      return temp.Value; 
     } 
     catch() 
     { 
      throw new Exception("Generic Fail Message"); 
     } 
    } 
+1

'Значение' не является свойством, определенным в типе' XObject'. – Will

0

Ответы @meganaut и @dasblinkenlight являются правильными, но есть еще что сказать.

В System.Linq.Xml пространстве имен, XElement и XAttribute как продлить XObject, но каждый из них определяют свою Value собственность отдельно, так что требуется такого рода разветвления или использование dynamic типа.

В других объектных моделях дженерики могут использоваться в аналогичном сценарии, предложенном @meganaut.