5

Json.Net と NHibernate をうまく連携させるには、まだ継続的な問題がありますつまり、プロキシされた NHibernate オブジェクトをシリアル化するために Json.NET を取得する場合です。

受け入れられた回答と修正の両方について、ここの推奨事項に従いましたが、サイコロはありません。

上記のソリューションの最大の問題は、NHibernate の最新バージョンがINHibernateProxyProxyインターフェイスを使用してプロキシを作成しているように見えることです (INHibernateProxy ではなく、他の誰かがこれを確認できますか?) NHibernate.Proxy.DynamicProxy.ProxyDummy。カスタム scontract リゾルバーを使用して Json コンストラクトを作成しようとすると、次のようになります。

    protected override JsonContract CreateContract(Type objectType)
    {
        if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType))
            return base.CreateContract(objectType.BaseType);
        else
            return base.CreateContract(objectType);
    }

INHibernateProxyProxy効果的に対処する方法について誰かアドバイスはありますか?

4

4 に答える 4

1

ずっと前からですが、ここでの問題は、実際には、プロキシをシリアル化する前に初期化されていなかったことだと思います。

NHibernateUtil.Initialize(aPersistentObject.LazyProperty);プロキシ オブジェクトを初期化するために呼び出す必要があります。

その後、BaseTypeおそらく正しかったでしょう...つまり、そうではProxyDummyなく、実際のタイプが必要でした。

私にとって、解決策は次のようなものです。

namespace com.example.DataAccess
{
    public static class Helper
    {
        // the implementation I use creates a ThreadStatic ISession, 
        // and then orphans and disposes that ISession when the 
        // result of this method is disposed.
        public static IDisposable GetSession(); 

        public static Type GetUnproxiedType(Type objectType)
        {
            if (typeof(INhibernateProxy).IsAssignableFrom(objectType))
                return objectType.BaseType;
            return objectType;
        }
        public static void Initialize(object proxy)
        {
            NHibernateUtil.Initialize(proxy);
        }
    }
}

namespace com.example.WebService
{
    internal static class Helper
    {
        private class ProxyResolver : CamelCasePropertyNamesContractResolver
        {
            protected override JsonContract CreateContract(Type objectType)
            {
                return base.CreateContract(DataAccess.Helper.GetUnproxiedType(objectType));
            }
        }

        public static readonly JsonSerializer serializer = new JsonSerializer
        {
            ContractResolver = new ProxyResolver(),
            Converters = 
                { 
                    new StringEnumConverter(),
                },
            DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
            Formatting = Formatting.Indented,
            // etc.
        };
    }
}

したがって、プロキシ型の REST サービス エンドポイントがある場合、次のようになります。

[WebGet(UriTemplate= "foo/{id}/bar")]
public Bar GetFooBar(string id)
{
    using (DataAccess.Helper.GetSession())
    {
        var foo = GetFoo(id);
        if (foo == null) return null;
        DataAccess.Helper.Initialize(foo.Bar);
        return foo.Bar;
    }
}

で定義されたシリアライザーWebService.Helperは、結果をシリアライズするために使用されます。

シリアル化プロセスがメソッドの外部で発生する場合 (私の場合のように)、実際にシリアル化する前にオブジェクトを初期化するために常に呼び出す必要があることに注意してください。イベントでこれを行うことができるかもしれませんがGlobal.asax、サービス メソッドで直接処理するだけです。

于 2015-11-19T02:15:45.277 に答える
1

それを見つけた。元のタイプは 経由.GetInterfaces()で利用できます。つまり:

    protected override JsonContract CreateContract(Type objectType)
    {
        if (typeof (INHibernateProxy).IsAssignableFrom(objectType))
        {
            var oType = objectType.GetInterfaces().FirstOrDefault(i => i.FullName.StartsWith("Your.Domain.Namespace"));
            return oType != null ? base.CreateContract(oType) : base.CreateContract(objectType.BaseType);
        }
        return base.CreateContract(objectType);
    }
于 2013-08-13T13:04:07.337 に答える
0

私の問題は、すべてのサブリストが Newtonsoft.JSON によって解決されるわけではないということでした。

コントラクトリゾルバーを追加しました

public class ProjectContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (typeof(INHibernateProxy).IsAssignableFrom(objectType))
        {
            if (objectType.FullName.Equals("DeviceModelProxy"))
                return CreateContract(typeof(DeviceModel));

            if (objectType.FullName.Equals("JobModelProxy"))
                return CreateContract(typeof(JobModel));

            base.CreateContract(objectType.BaseType);
        }
        return base.CreateContract(objectType);
    }
}

シリアル化時に、カスタム コントラクト リゾルバーを追加します

JsonConvert.SerializeObject(backupDataModel, Formatting.Indented, new JsonSerializerSettings()
        {
            ContractResolver = new ProjectContractResolver()
        });

これは私の問題を解決します。

于 2018-06-26T10:38:04.620 に答える