Bonjour, je sais que c'est vieux mais j'ai pensé ajouter quelques compléments à la réponse d'Ayendes pour aider les gens qui comme moi ont eu le même problème et ont passé des heures à chercher une réponse sur les forums (il y en avait quelques uns mais aucun n'avait d'exemple à suivre), ce n'est pas difficile à comprendre mais avec un exemple j'aurais pu le résoudre en 10 minutes au lieu de passer quelques heures.
Mon problème est que nous avons des structures de type valeur personnalisées dans notre application, l'exemple que j'utiliserai est EmailAddress. Malheureusement, dans Ravendb, nous ne pouvions pas exécuter de requêtes sur ces types sans définir un sérialisateur personnalisé.
Notre type de valeur se présente comme suit :
[DataContract(Namespace = DataContractNamespaces.ValueTypes)]
public struct EmailAddress : IEquatable<EmailAddress>
{
private const char At = '@';
public EmailAddress(string value) : this()
{
if (value == null)
{
throw new ArgumentNullException("value");
}
this.Value = value;
}
public bool IsWellFormed
{
get
{
return Regex.IsMatch(this.Value, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
}
}
public string Domain
{
get
{
return this.Value.Split(At)[1];
}
}
[DataMember(Name = "Value")]
private string Value { get; set; }
public static bool operator ==(EmailAddress left, EmailAddress right)
{
return left.Equals(right);
}
public static bool operator !=(EmailAddress left, EmailAddress right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return this.Equals(new EmailAddress(obj.ToString()));
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
public bool Equals(EmailAddress other)
{
return other != null && this.Value.Equals(other.ToString(), StringComparison.OrdinalIgnoreCase);
}
}
Le type de document que nous voulons sauvegarder et interroger ressemblerait à ceci
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public EmailAddress Email { get; set; }
}
Le sérialiseur personnalisé pour stocker notre courriel en tant que chaîne brute et le reconvertir en son type de valeur lors de la récupération ressemblait à ceci :
public class EmailConverterTest : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(EmailAddress);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
EmailAddress actualAddress = new EmailAddress(reader.Value.ToString());
return actualAddress;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
EmailAddress actualAddress = (EmailAddress)value;
string stringEmail = actualAddress.ToString();
writer.WriteValue(stringEmail);
}
}
Finalement, j'ai câblé le tout et j'ai pu interroger tout ce qui suit :
public static void serializercustom(Newtonsoft.Json.JsonSerializer serialiser)
{
serialiser.Converters.Add(new EmailConverterTest());
}
public static void TestCustomer()
{
using (var documentStore = new DefaultDocumentStore())
{
documentStore.ConnectionStringName = Properties.Settings.Default.SandBoxConnection;
documentStore.Initialize();
documentStore.Conventions.CustomizeJsonSerializer = new Action<Newtonsoft.Json.JsonSerializer>(serializercustom);
var customer = new Customer
{
Id = Guid.NewGuid(),
FirstName = "TestFirstName",
LastName = "TestLastName",
Email = new EmailAddress("testemail@gmail.com")
};
// Save and retrieve the data
using (var session = documentStore.OpenSession())
{
session.Store(customer);
session.SaveChanges();
}
using (var session = documentStore.OpenSession())
{
var addressToQuery = customer.Email;
var result = session.Query<Customer>(typeof(CustomerEmailIndex).Name).Customize(p => p.WaitForNonStaleResults()).Where(p => p.Email == addressToQuery);
Console.WriteLine("Number of Results {0}", result.Count()); // This always seems to return the matching document
}
}
}