asp.net异步的不当使用方式
在进行asp.net ajax设计的时候,我们肯定避免不了利用JQuery的ajax函数取调用HttpHandler中的数据.在我开始学习的时候,我总是这么用的,那时候头脑中没有什么概念,只知道有了新需求就新增ashx文件,复制粘贴原有的ajax请求代码,稍微修改一下即可. 所以文件中总是充斥着大量的可粘贴复制的代码:
$.ajax({ type : "post", contentType: "application/json", datatype : "json", url : "WebHandler.ashx/GetUserList", data : "{UID:1}", success : function(data) { alert("ok") } });
这样做的好处就是自己很开心,也费不了多少时间就可以将功能修改好.但是带来的负面效果将是致命的.
(1) 大量的代码结构基本上一致,粘贴复制不但容易出错,而且项目一大,修改起来就比较麻烦.倘若一个地方出错, 好多地方修改.
(2) 代码中的URL请求非常不保险,一旦项目结构发生变化,路径发生变化,项目的修改就需要跟进,项目一大,这种修改是致命的.
(3) 这种工作不能很好的协调前端开发和后端开发, 由于前端直接通过ajax请求后端数据,导致二者的配合需要非常紧密(前端设计有时候需要看后端代码去确定需要调用哪个方法).不好独立的进行开发.
(4) 就是有违软件设计软则,大量重复代码充斥,后期维护困难,牵一发而动全身.
比较好的解决方式
所以基于以上几点,决定针对这四点着重解决.
(1) 大量重复代码可以写到一个公共的js文件中,然后将请求文件参数当作参数传出:
$.ajaxRequest("WebHandler.ashx/GetUserList ", "{}", function(result) {......});
这样使用的时候,直接添加好js文件,然后调用即可.只关注逻辑,代码量显著下降.
(2) 当项目文件改变的时候,上面的方法显然无法解决问题,所以最好能够将url自动检测. 所以我期望的是这样调用:
$.ajaxRequest.GetUserList (“{}”, function (result {……}) ;
这样就解决了项目变动,不能找到handler文件的问题.
(3) 这个问题,可以通过新增一个中间文件来解决.最好的办法就是客户端请求时,后台能够动态生成供前台调用的js代码.
(4) 这个主要是代码编写这块. 与设计方面暂无关系.
所以,总结一下,就是由原先的前台通过ajax直接发送请求到后台,然后后台返回数据的过程, 修改成了前台通过ajax发出请求,后台动态生成js中间文件,前台然后调用即可.
所以这里我总结一下我们的需求,
就是,前台发送$.ajaxRequest.GetUserList (“{}”, function (result {……}) ;出去,后台接收之后,动态创建js文件,然后供前台调用.
那么这里我们需要的东西就是,一个js模板,能够承载动态生成的函数, 一个ashx文件,能够接收请求,并且读取模板并修改之.
代码阅读
模板代码我就不写了,直接找现成的, 感谢作者的开源:
然后就是后台代码,我已经加入了主要的注释,各位看官请看好.
总之,操作过程就是,有请求发来,就动态在JS中生成与服务端一致的签名函数,然后客户端调用.
这里,我们可以添加点函数来测试:
后台:
前台调用部分:
看上去是不是简洁了许多?
需要说明的是,我们还有很多方式来让前台调用后台,除了这种利用反射来动态生成中间JS文件以外,我们还可以通过在服务端维护一个Dictionary来进行,Dictionay的key存储函数签名,value存储函数体,这也是一种不错的设计方式.
效果图展示
参考:
非常感谢这篇博客,一个基于jQuery ajax和.net httphandler 的超轻异步框架,千行代码完成。
源码下载
点击这里下载
今日,在项目重构的时候忽然想到一个问题,一个类哪些成员的增加,会影响一个类所占内存的大小?C#有没有办法知道一个对象占多少内存呢?
第一个问题:很快想到是类的非静态的字段、属性。
第二个问题:首先想到的是sizeof()。
下面开始验证,首先来验证值类型,验证代码如下:
int size = sizeof (int); //4个字节
注意点:sizeof 运算符仅适用于值类型,而不适用于引用类型。sizeof 运算符只能在不安全代码块中使用。如下面的代码将无法编译通过:
public struct TestStuct { } int size = sizeof(new TestStuct());
编译后,提示:
错误 1 “ConsoleApplication3.TestStuct”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用(请考虑使用 System.Runtime.InteropServices.Marshal.SizeOf)
修改为Marshal.SizeOf方法,改方法返回对象的非托管大小(以字节为单位)。参数可以是引用类型或装箱的值类型。布局必须是连续的或显式的。
int size = Marshal.SizeOf(new TestStuct()); //1个字节
接下来来验证引用类型:
由于不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。所有下面的代码在运行的时候,会抛出异常。
public class Student { } int size = Marshal.SizeOf(new Student());
需要给Student类,加上一个StructLayoutAttribute,来控制Student类的数据字段的物理布局。修改代码为:
[StructLayout(LayoutKind.Sequential)] public class Student { } int size = Marshal.SizeOf(new Student()); //1个字节
LayoutKind 默认值为Auto.
结论:
1:对于托管对象是没有办法直接获取到一个对象所占的内存大小。
2:非托管对象,可以使用Marshal.SizeOf
3:对内置类型,如int,long,byte等使用sizeof
扩展:
有人提出使用二进制序列化,将一个对象序列化成一个MemoryStream,然后返回MemoryStream.Length,经过验证是不可以的。
验证代码如下:
[Serializable] public class Student { } private static long GetObjectSize(object o) { using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, o); using (var fileStream = new FileStream(@"D:\Student.txt", FileMode.OpenOrCreate, FileAccess.Write)) { var buffer = stream.ToArray(); fileStream.Write(buffer, 0, buffer.Length); fileStream.Flush(); } return stream.Length; } } var student = new Student(); long size = GetObjectSize(student); //139个字节
Student.txt保存的文本信息如下所示,通过文本信息,可以得知多出来的100多个字节,估计是就是这一串字符串吧。
JConsoleApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ConsoleApplication3.Student
延伸阅读:
http://blogs.msdn.com/b/cbrumme/archive/2003/04/15/51326.aspx
原文如下:
We don't expose the managed size of objects because we want to reserve the ability to change the way we lay these things out. For example, on some systems we might align and pack differently. For this to happen, you need to specify tdAutoLayout for the layout mask of your ValueType or Class. If you specify tdExplicitLayout or tdSequentialLayout, the CLR’s freedom to optimize your layout is constrained.
If you are curious to know how big an object happens to be, there are a variety of ways to discover this. You can look in the debugger. For example, Strike or SOS (son-of-strike) shows you how objects are laid out. Or you could allocate two objects and then use unverifiable operations to subtract the addresses. 99.9% of the time, the two objects will be adjacent. You can also use a managed profiler to get a sense of how much memory is consumed by instances of a particular type.
But we don't want to provide an API, because then you could form a dependency over this implementation detail.
Some people have confused the System.Runtime.InteropServices.Marshal.SizeOf() service with this API. However, Marshal.SizeOf reveals the size of an object after it has been marshaled. In other words, it yields the size of the object when converted to an unmanaged representation. These sizes will certainly differ if the CLR’s loader has re-ordered small fields so they can be packed together on a tdAutoLayout type.