我有一个数据访问层,一服务层和表示层。表示层ASP.NET MVC2 RTM(网页),和业务层是WCF(服务)。它的所有.NET 3.5 SP1。

的问题是,在服务,正在返回的对象都标有[DataContract]属性。该网站使用的AppFabric缓存(a.k.a速度)SessionStateProvider存储会话状态。由于这个原因,在会话什么我店必须可序列化。

这里谈到的问题:DataContracts都没有标明[Serializable]而据我的记忆,通过将其上已经打上[DataContract]出现的一些问题的一类,所以我不相信这是一个解决方案。

我最初打算使用正好在网层的DataContracts,使用它们作为模型来与呈现DataContracts次(大概嵌套更高水平ViewModel类内侧)。但由于需要存储在它里面是序列化的所有对象的会话状态提供者,我开始重新考虑这一策略。这将是不错的,虽然,因为它们使用IDataErrorInfo接口包含验证逻辑,和相同的验证逻辑可以被重新使用在MVC作为结合模型的一部分。

你相信什么,是让我减少所需的工作的最好方式?

我目前认为以下不同的方式:

:一种。创建在web项目 'ServiceIntegration' 部分。

这将是我的控制器和我的WCF服务层之间的中间人。所述ServiceIntegration部分将向服务层使用DataContracts使用的ViewModels说话,到Web层,但必须使用一个双向变压器的DataContracts和的ViewModels之间变换。

另外,由于IDataErrorInfo的验证不会重复使用的,这将是必要的,以创建每DataContract太一个验证程序,使用该变压器转换从视图模型到DataContract,使用IDataErrorInfo的执行验证并返回它的结果。这然后将内部控制器的动作方法中使用(例如if (!MyValidator.IsValid(viewModel)) return View();

所需的不同的类:xDataContract,xViewModel,xTransformer,xValidator

<强> B中。在web项目创建 'SessionIntegration' 部分

这将是控制器(或任何访问会话)和会话本身之间的中间人。任何需要访问会话会去通过这个类。 DataContracts将在整个应用程序中使用,除非它们被存储到会话中。该SessionIntegration部分将采取改造DataContract一些ISerializable的形式,和背部的责任。因为使用对DataContract IDataErrorInfo的接口中的每一个不需要附加的验证。

所需的不同的类:xDataContract,xTransformer,xSerializableForm


注意:仍然会有的ViewModels围绕在这两种情况下,但是与(B)我能够从DataContracts撰写的ViewModels

(B)具有不需要额外的验证的益处。


在我熄灭和执行(A)/(B)充分,我想一些反馈。目前,我开始朝(B)倾斜,但是,(A)可能会更灵活。无论哪种方式,它看起来像它的价值了太多的工作。有没有其他人遇到这个问题,你是否同意/不同意我,和/或你有解决问题的任何其他方式?

谢谢,

詹姆斯

有帮助吗?

解决方案

没有去A或B的完全成熟的路线,你可以只让一个通用ISerializable的包装对象,把那些在您的SessionState的?

    [Serializable]
    public class Wrapper : ISerializable
    {
        public object Value { get; set; }

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (Value != null)
            {
                info.AddValue("IsNull", false);
                if (Value.GetType().GetCustomAttributes(typeof(DataContractAttribute), false).Length == 1)
                {
                    using (var ms = new MemoryStream())
                    {
                        var serializer = new DataContractSerializer(Value.GetType());
                        serializer.WriteObject(ms, Value);
                        info.AddValue("Bytes", ms.ToArray());
                        info.AddValue("IsDataContract", true);
                    }
                }
                else if (Value.GetType().IsSerializable)
                {
                    info.AddValue("Value", Value);
                    info.AddValue("IsDataContract", false);
                }
                info.AddValue("Type", Value.GetType());
            }
            else
            {
                info.AddValue("IsNull", true);
            }
        }

        public Wrapper(SerializationInfo info, StreamingContext context)
        {
            if (!info.GetBoolean("IsNull"))
            {
                var type = info.GetValue("Type", typeof(Type)) as Type;

                if (info.GetBoolean("IsDataContract"))
                {
                    using (var ms = new MemoryStream(info.GetValue("Bytes", typeof(byte[])) as byte[]))
                    {
                        var serializer = new DataContractSerializer(type);
                        Value = serializer.ReadObject(ms);
                    }
                }
                else
                {
                    Value = info.GetValue("Value", type);   
                }
            }
        }
    }

其他提示

作为扩展到所提供的答案,我添加这两种方法,以减轻存储/检索数据。

    public static void Set<T>(HttpSessionStateBase session, string key, T value)
    {
        session[key] = new Wrapper(value);
    }

    public static T Get<T>(HttpSessionStateBase session, string key)
    {
        object value = session[key];
        if (value != null && typeof(T) == value.GetType())
        {
            return (T) value;
        }
        Wrapper wrapper = value as Wrapper;
        return (T) ((wrapper == null) ? null : wrapper.Value);
    }

这使得它来设置更容易一些/从会议上得到的值:

    MyDataContract c = ...;
    Wrapper.Set(Session, "mykey", c);
    c = Wrapper.Get<MyDataContract>(Session, "mykey");

要使其更容易,添加扩展方法:

public static class SessionWrapperEx
{
    public static void SetWrapped<T>(this HttpSessionStateBase session, string key, T value)
    {
        Wrapper.Set<T>(session, key, value);
    }

    public static T GetWrapped<T>(this HttpSessionStateBase session, string key)
    {
        return Wrapper.Get<T>(session, key);
    }
}

和使用如下:

    MyDataContract c = ...;
    Session.SetWrapped("mykey", c);
    c = Session.GetWrapped<MyDataContract>("mykey");
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top