Поместить объекты, которые украшены [DataContract] в StateServer? - PullRequest
3 голосов
/ 13 марта 2010

Есть ли в любом случае прикрепить объекты, которые украшены DataContract атрибутами, но не украшены Serializable атрибутами в SqlServer StateServer? Другими словами, я бы предпочел не украшать эти объекты атрибутом Serializable, поскольку мне также придется реализовать IXmlSerizable для всех этих объектов, поскольку у них нет пустых конструкторов и закрытых сеттеров для свойств. *

Ответы [ 2 ]

2 голосов
/ 13 марта 2010

Нет абсолютно простого способа сделать это, к сожалению, нет.

Но: механизм состояния сеанса ASP.NET является расширяемым, так что вы можете представить свой собственный поставщик состояний сеансов ASP.NET, который в основном использует DataContractSerializer и сохраняет сериализованные объекты в SQL Server (или любом другом хранилище, для этого материя).

Извлечение Режимы состояния сеанса MSDN и Реализация поставщика хранилища состояний сеанса .

Не простой маленький переключатель для щелчка - но это определенно выполнимо.

Или просто украсьте свои объекты [Serializable] и покончите с этим ...

1 голос
/ 17 января 2013

Я думаю, что вам нужно реализовать ISerializable и вручную сериализовать с помощью DataContractSerializer.

Посмотрите ответ здесь:

Использование WCF DataContract в MVC SessionState с использованием кэша AppFabric

Хотя речь идет об использовании AppFabric (StateServer), та же проблема относится и к SqlSessionStateStore (все OOB StateProviders используют BinaryFormatter для графиков сложных объектов)

Мне просто нужно было сделать это в проекте, и он отлично работал. (и это было легко-peasy)

В моем случае, однако, я не хотел сериализовать только элементы, помеченные [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);
            }
        }
    }
}
...