6

次のようなクラスがあります。

public class MyClass
{
    string _value;

    public static implicit operator MyClass (string value)
    {
        return new MyClass(value);
    }

    MyClass(string value)
    {
        // Do something...
        _value = value;
    }

    public override string ToString()
    {
         // Do something...
         return _value;
    }
}

したがって、次のようにクラスを使用できます。

MyClass a = "Hello!";

しかし、Raven DBでは、次のように保存されます

"SomeProperty": {}

パブリック プロパティがないためです。そして、それはまったく役に立たない。

これを解決するには、次のように、代わりに _value プライベート メンバーをパブリック プロパティにします。

public string Value { get; set; }

そしてRaven DBは保存します

"SomeProperty": { "Value": "Hello!" }

そしてそれはデシリアライズ可能になります。

しかし、私はこの公共の財産を望んでいません。文字列の場合と同じように、Raven DB でクラスをシリアライズおよびデシリアライズすることはできますか? お気に入り:

"SomeProperty": "Hello!"
4

2 に答える 2

12

こんにちは、私はこれが古いことを知っていますが、私のように同じ問題を抱えていて、フォーラムで何時間もかけて回答を探している人を助けるために、Ayendes の返信にいくつかの追加を追加すると思いました (そのうちのいくつかはありましたが、そのような例はありませんでした)従うことができます)、これを理解するのは難しくありませんが、例を使用すると、数時間を費やすのではなく、10 分でこれを解決できたはずです。

私の問題は、アプリケーションにカスタム値型の構造体があることでした。使用する例は EmailAddress です。残念ながら、Ravendb では、カスタム シリアライザーを定義しないと、これらの型に対してクエリを実行できませんでした。

値の型は次のようになります。

[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);
    }
}

保存してクエリしたいドキュメントのタイプは、次のようになります。

public class Customer
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public EmailAddress Email { get; set; }
}

メールを生の文字列として保存し、取得時に値の型に戻すカスタム シリアライザーは次のようになります。

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);
    }
}

最後に、私はそれを配線し、次のようにすべてを照会することができました:

    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
            }
        }
    } 
于 2012-08-24T00:38:25.413 に答える
6

JsonConverterを作成し、データの保存方法をRavenDBに教えることができます。コンバーターを作成したら、store.Conventions.CustomizeSerializerイベントに登録します。

于 2012-05-18T07:33:05.533 に答える