DataContract
属性で装飾されているが属性で装飾されていないオブジェクトをSerializable
SqlServerStateServerに貼り付ける方法はありますか?つまり、これらのオブジェクトにSerializable
は空のコンストラクターとプロパティの非公開セッターがないため、これらのオブジェクトすべてにIXmlSerizableを実装する必要があるため、これらのオブジェクトを属性で装飾する必要はありません。
2 に答える
残念ながら、これを行うための絶対に簡単な方法はありません。
ただし、ASP.NETセッション状態メカニズムは拡張可能であるため、基本的にDataContractSerializerを使用し、シリアル化されたオブジェクトをSQL Server(またはその他のストア)に格納する独自のASP.NETセッション状態プロバイダーを作成することを想像できます。
MSDNセッション状態モードとセッション状態ストアプロバイダーの実装を確認してください。
フリックへの単純な小さな切り替えではありませんが、それは間違いなく実行可能です。
または、オブジェクトを装飾して、それで[Serializable]
完了します...
ISerializableを実装し、DataContractSerializerを使用して手動でシリアル化することが必要だと思います。
ここで答えを見てください:
AppFabricキャッシュを使用したMVCSessionStateでのWCFDataContractの使用
これはAppFabric(StateServer)の使用について話している間、同じ問題がSqlSessionStateStoreにも当てはまります(すべてのOOB StateProviderは複雑なオブジェクトグラフにBinaryFormatterを使用します)
私はプロジェクトでこれをしなければならなかった、そしてそれはうまくいった。(そしてそれは簡単でした-簡単でした)
ただし、私の場合、[DataContract]クラスは階層全体にネストされており、すべてのレベルでこれらのエンティティをすべてラップしたくないため、[DataContract]でマークされたアイテムのみをシリアル化する必要はありませんでした。(DataContractアイテムは、状態オブジェクトのバッキングデータとして使用されるサービス参照DTOです)。代わりに、セッションに詰め込んでいたアイテムのメンバーであるルート要素を単純にラップしました。
それを理解するのはちょっと難しいので、以下のコードを含めました。
/// <summary>
/// Represents a thread-safe, per-session state object, stored in the ASP.NET Session.
/// </summary>
[Serializable]
public class SessionContext
{
#region Static
private const string SESSION_CONTEXT_KEY = "SessionContext";
private static object _syncRoot = new object();
public static SessionContext Current
{
get
{
HttpSessionState session = HttpContext.Current.Session;
if (session[SESSION_CONTEXT_KEY] == null)
{
lock (_syncRoot)
{
if (session[SESSION_CONTEXT_KEY] == null)
{
session[SESSION_CONTEXT_KEY] = new SessionContext();
}
}
}
return (SessionContext)session[SESSION_CONTEXT_KEY];
}
}
#endregion
private SessionContext()
{
}
public User User { get; set; }
private CustomerWrapper _customerWrapper = new CustomerWrapper();
/// <summary>
/// ignore serializing the Customer object because we're serializing the wrapper object instead, which uses the more robust DataContractSerializer.
/// </summary>
[XmlIgnore]
public Customer Customer
{
get
{
return this._customerWrapper.Customer;
}
set
{
this._customerWrapper.Customer = value;
}
}
}
/// <summary>
/// Custom wrapper object to instruct the OutOfProc StateProvider how to serialize this item.
/// Instead of using the BinaryFormatter, we'll use the more robust DataContractSerializer.
/// </summary>
[Serializable]
public class CustomerWrapper : ISerializable
{
public Customer Customer { get; set; }
internal CustomerWrapper() { }
internal CustomerWrapper(Customer customer) : this() { this.Customer = customer; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (this.Customer != null)
{
info.AddValue("IsNull", false);
using (var ms = new MemoryStream())
{
try
{
var serializer = new DataContractSerializer(this.Customer.GetType());
serializer.WriteObject(ms, this.Customer);
info.AddValue("Bytes", ms.ToArray());
info.AddValue("IsDataContract", true);
}
catch (Exception ex)
{ // breakpoint never hit
}
}
info.AddValue("Type", this.Customer.GetType());
}
else
{
info.AddValue("IsNull", true);
}
}
public CustomerWrapper(SerializationInfo info, StreamingContext context)
{
if (!info.GetBoolean("IsNull"))
{
var type = info.GetValue("Type", typeof(Type)) as Type;
using (var ms = new MemoryStream(info.GetValue("Bytes", typeof(byte[])) as byte[]))
{
var serializer = new DataContractSerializer(type);
this.Customer = (Customer)serializer.ReadObject(ms);
}
}
}
}