以下是我为了在服务端和客户端中通过CallContext进行传送的类型定义
 [Serializable]
    public class UserToken : ILogicalThreadAffinative
    {        public SqlGuid m_Session;        public UserToken(SqlGuid session)
        {
            m_Session = session;
        }        public SqlGuid SessionId
        {
            get
            {
                return m_Session;
            }
            set
            {
                m_Session = value;
            }
        }        //以下两个函数是据微软的文档所说的解决方法,不过一点也没有效果,不知错在那里了.
        public new int GetHashCode()
        {
            return base.GetHashCode();
        }        public new Type GetType()
        {
            return base.GetType();
        }
    }    原先我以为CallContext中的传输的对像会一直保留,结果确不是这样.过程如下:
    我设计了一个服务组件,其中一个方法会调用CallContext.SetData存入一个上述类型的对象,客户端也可以正常调用CallContext.GetData得到这个对象,然而当我再次应用客户端激活一个新的服务端对象时,CallContext中的数据确被清掉了,并得到提示"试图访问调用方不可访问的字段",为什么会这样?微软的文档说如果类型不实现ILogicalThreadAffinative接口,就不会被清掉,但不能进行远程传送,对我没什么意义.
我希望这个对像总是被传送,而不会被清掉.因为我希望它用于标识客户会话标识,表示客户是经过验证的合法客户.

解决方案 »

  1.   

    原代码全部搞出来,帮你交流,我也喜欢Remoting
      

  2.   

    找到问题了,是public SqlGuid m_Session;惹得祸,改成public string m_Session;就没事了.
    怪,System.Data.SqlTypes.SqlGuid类型是支持序列化的,而且从服务端传到客户端没事,但从客户端传到服务端就有问题了(会提示那个"试图访问调用方不可访问的字段"错误,然后CallContext中的Sessionid数据项就被清掉了),不懂出了什么问题.我用的是.net 2.0版本,vs2005开发.
    以下是服务端代码:
        [Serializable]
        public class UserToken : ILogicalThreadAffinative
        {        public string m_Session;        public UserToken(SqlGuid session)
            {
                m_Session = session.ToString() ;
            }        public SqlGuid SessionId
            {
                get
                {
                    return new SqlGuid(m_Session);
                }
                set
                {
                    m_Session = value.ToString();
                }
            }
        }    //登陆的远程激活类,登陆成功后将返回一个令牌,并有意在后期也加入一个相关的客户ip地址的验证,而不止是会话标识    public class LoginVerification : MarshalByRefObject
        {
            public UserToken Login(string username, string pwd)
            {
                SqlConnection conn = DBConnString.Conn;
                SqlCommand comm = new SqlCommand("bLogin", conn);
                comm.CommandType = CommandType.StoredProcedure;            SqlParameter pUname = new SqlParameter( "@Uname",SqlDbType.VarChar , 50 );
                pUname.Direction = ParameterDirection.Input;
                pUname.Value = username;
                comm.Parameters.Add(pUname);            SqlParameter pPwd = new SqlParameter("@Pwd", SqlDbType.VarChar, 1024);
                pPwd.Direction = ParameterDirection.Input;
                pPwd.Value = pwd;
                comm.Parameters.Add(pPwd);            SqlParameter pSessionid = new SqlParameter("@Sessionid", SqlDbType.UniqueIdentifier);
                pSessionid.Direction = ParameterDirection.Output;
                comm.Parameters.Add(pSessionid);            try
                {
                    comm.ExecuteNonQuery();
                    if (pSessionid.Value == DBNull.Value )
                    {
                        throw new Exception("用户名或密码不正确");
                   //     return null;// new UserToken(SqlGuid.Null);
                    }
                    else
                    {
                        UserToken temp = new UserToken(new SqlGuid(pSessionid.Value.ToString()));
                        CallContext.LogicalSetData("Sessionid", temp);
                        return temp;
                    }
                }
                catch (SqlException sqlerr)
                {
                    throw new Exception("运行时数据库出错:"+sqlerr.Message);
                }
                finally
                {
                    conn.Close();
                    comm.Dispose();
                }
            }
        }客户端与服务端均很普通,没什么特别的地方.