Por que não é o meu DbNull um singleton quando eu desserializar-lo usando XmlSerializer?
-
09-09-2019 - |
Pergunta
Eu sempre assumiu que DBNull.Value era um solteirão. E, assim, você pode fazer coisas como esta:
VB.NET:
If someObject Is DbNull.Value Then
...
End if
C #:
If (someObject == DbNull.Value)
{
...
}
Mas, recentemente, eu serializado um exemplo DbNull usando o XmlSerialiser e de repente não era um solteirão mais. operações de comparação tipo (como 's (obj é DBNull) C #) trabalho OK embora.
código a seguir:
[Serializable, System.Xml.Serialization.XmlInclude(typeof(DBNull))]
public class SerialiseMe
{
public SerialiseMe() { }
public SerialiseMe(object value)
{
this.ICanBeDbNull = value;
}
public Object ICanBeDbNull { get; set; }
}
public void Foo()
{
var serialiseDbNull = new SerialiseMe(DBNull.Value);
var serialiser = new System.Xml.Serialization.XmlSerializer(typeof(SerialiseMe));
var ms = new System.IO.MemoryStream();
serialiser.Serialize(ms, serialiseDbNull);
ms.Seek(0, System.IO.SeekOrigin.Begin);
var deSerialisedDbNull = (SerialiseMe)serialiser.Deserialize(ms);
// Is false, WTF!
var equalsDbNullDeserialised = deSerialisedDbNull.ICanBeDbNull == DBNull.Value;
// Is false, WTF!
var refEqualsDbNullDeserialised = object.ReferenceEquals(deSerialisedDbNull.ICanBeDbNull, DBNull.Value);
// Is true.
var convertIsDbNullDeserialised = Convert.IsDBNull(deSerialisedDbNull.ICanBeDbNull);
// Is true.
var isIsDbNullDeserialised = deSerialisedDbNull.ICanBeDbNull is DBNull;
}
Por que é este o caso? E como isso acontece? E isso pode acontecer com quaisquer outros campos estáticos?
PS: Estou ciente do exemplo de código VB está fazendo uma comparação de referência e c # está chamando Object.Equals. Ambos têm o mesmo comportamento com DBNull. Eu costumo trabalhar com VB.
Solução
Embora DBNull.Value
é um static readonly
e só existe como uma única instância ... quando você de-serialize, o código de serialização seria a criação de uma nova instância do DBNull
classe a partir dos dados "no fluxo. Desde o DBNull.Value
é simplesmente uma instância DBNull
, não há nenhuma maneira para serialização de saber que é uma instância de 'especial'.
NOTA:
Pela mesma razão, se você fizer sua própria classe com uma instância 'solteirão' que você serializar e depois de-serialize você vai obter exatamente o mesmo comportamento. Embora a instância desserializada será indistinguível da instância original, eles não serão a mesma instância .
Outras dicas
O seu código c # não é igual a chamar o método .Equals. Sem ter testado Im realmente muito certo se você Substituição
someObject == DbNull.Value
com
DbNull.Value.Equals(someObject)
que lhe daria o resultado esperado. Para algumas entranhas sobre o operador de igualdade e o método Equals dar uma olhada: Eric Lipperts post sobre esse assunto