7月 22

记得曾经使用ASP.NET AJAX的时候有个webmethod方法,可以在客户端直接调用aspx.cs里面的cs文件.

非常方便,可惜要引用ScriptManager,今天咱自己实现一下,非常好用

    /// <summary>
    /// Summary description for AJAX
    /// </summary>
    public class AJAX : IHttpHandler, IRequiresSessionState
    { 
        static Dictionary<string, Func<HttpContext, AuthInfo, string>> dic = null;
        static Dictionary<string, int> PermissionTree = null;
        static AJAX()
        { 
            dic = new Dictionary<string, Func<HttpContext, AuthInfo, string>>();
            PermissionTree = new Dictionary<string, int>();

            var assembly = System.Reflection.Assembly.GetAssembly(typeof(AJAX));

            var types = assembly.GetTypes();
            foreach (var type in types)
            {
                MethodInfo[] methodInfos = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
                foreach (var methodInfo in methodInfos)
                {
                    if (methodInfo.IsDefined(typeof(Ascend.Framework.Infrastructure.Web.AjaxAttribute), true))
                    {

                        string fullname = type.FullName.ToLower() + "." + methodInfo.Name.ToLower();

                        {
                            var attributes = methodInfo.GetCustomAttributes(typeof(AjaxAttribute), false);
                            var attribute = (AjaxAttribute)attributes[0];
                            int PermissionCode = attribute.PermissionCode;
                            string ActionName = attribute.ActionName;
                            if (ActionName != null)
                            {
                                fullname = ActionName;
                            }
                            if (PermissionCode > 0)
                            {
                                PermissionTree.Add(fullname, PermissionCode);
                            }
                        }
                        try
                        {
                            Func<HttpContext, AuthInfo, string> func = (Func<HttpContext, AuthInfo, string>)Delegate.CreateDelegate(typeof(Func<HttpContext, AuthInfo, string>), methodInfo);

                            dic.Add(fullname, func);
                        }
                        catch (Exception ex)
                        { 
                        
                        }
                    }
                }
            }
        } 

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";

            string action = context.Request["action"];
            string data = string.Empty;

            AuthInfo authInfo = null;
            if (context.Session["authinfo"] != null)
            {
                authInfo = (AuthInfo)context.Session["authinfo"];

                if (PermissionTree.ContainsKey(action)) //需要权限代码
                {
                    var code = PermissionTree[action];
                    if (!authInfo.Functions.Contains(code))
                    {
                        ResultInfo result = new ResultInfo(false, -3, "No permission");
                        data = Ascend.Framework.Infrastructure.Serialization.JSONSerializer.Serialize(result);
                        context.Response.Write(data);
                        return;
                    }
                }

                if (dic.ContainsKey(action))
                {
                    data = dic[action](context, authInfo);

                    LogFactory.Operator.Message(authInfo.UserId, authInfo.RealName, action);

                }
                else
                {
                    ResultInfo result = new ResultInfo(false, -2, "没有找到调用方法:" + action);
                    data = Ascend.Framework.Infrastructure.Serialization.JSONSerializer.Serialize(result);
                }
            }


            else if (action == "login")
            {
                data = dic[action](context, authInfo);
            }
            else
            {
                ResultInfo result = new ResultInfo(false, -1, "Login timeout, please login again");
                data = Ascend.Framework.Infrastructure.Serialization.JSONSerializer.Serialize(result);
            }

            context.Response.Write(data);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }

初始化的时候会通过反射自动遍历当前项目中所有添加AjaxAttribute标记的方法,他们都具有相同的方法签名

public static string Add(HttpContext content, AuthInfo authInfo)

将委托方法加到Dictionary中缓存起来,方法形式如

        [Ascend.Framework.Infrastructure.Web.Ajax(131)]
        public static string Add(HttpContext content, AuthInfo authInfo)
        {
            try
            { 
                BrandInfo brandInfo = new BrandInfo();
                brandInfo.B_BrandCode = content.Request["B_BrandCode"];
                brandInfo.B_Description = content.Request["B_Description"];
                brandInfo.B_Remark = content.Request["B_Remark"];
                brandInfo.B_CreateBy = authInfo.RealName;
                brandInfo.B_CreateDate = DateTime.Now;
                brandInfo.B_IsActive = content.Request["B_IsActive"].ToBoolean(false); 
                IBrand brandService = ServiceFactory.GetService<IBrand>();
                var result = brandService.AddBrand(brandInfo);
                return Ascend.Framework.Infrastructure.Serialization.JSONSerializer.Serialize(result); 
            }
            finally
            {
                LogFactory.Operator.Message(authInfo.UserId, authInfo.UserName, 131, null);
            }
        }

另外方法参数里加入了权限验证代码,一举完成验证和调用方法的统一.还有操作日志的记录,也在同时完成.

另外在写这篇post的时候我突然想到,其实完全可以把错误日志也放在里面记录下来,修改代码如下

                if (dic.ContainsKey(action))
                {
                    try
                    {
                        data = dic[action](context, authInfo);
                    }
                    catch (Exception ex)
                    {
                        //todo
                    }
                    LogFactory.Operator.Message(authInfo.UserId, authInfo.RealName, action); 
                }

这个未测试

前台调用很简单

直接ajax请求这个地址就好啦

../ajax.ashx?action=itrazv2.mainweb.stockmodule.brandpage.add

written by ocean

7月 16

先抄一段nginx的介绍:

Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

官方地址 :http://nginx.org/

 

首先下载

wget http://nginx.org/download/nginx-1.7.3.tar.gz

移动

mv nginx-1.7.3.tar.gz /usr/local/nginx-1.7.3.tar.gz

解压

tar zxvf nginx-1.7.3.tar.gz

删除安装包

rm -rf nginx-1.7.3.tar.gz

解压包改名

mv nginx-1.7.3 nginx

 

安装Nginx之前需要确保系统安装了g++、gcc、openssl-devel、pcre-devel和zlib-devel软件

yum install gcc-c++
yum -y install zlib zlib-devel openssl openssl--devel pcre pcre-devel

 

./configure是用来检测你的安装平台的目标特征的。比如它会检测你是不是有CC或GCC,并不是需要CC或GCC,它是个shell脚本。

./configure --prefix=/usr/local/nginx

make是用来编译的,它从Makefile中读取指令,然后编译。

make

make install是用来安装的,它也从Makefile中读取指令,安装到指定的位置。

make install

 

修改防火墙

#修改防火墙配置:
 [root@admin nginx-1.2.6]# vi + /etc/sysconfig/iptables
#添加配置项
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
#重启防火墙
[root@admin nginx-1.2.6]# service iptables restart

 启动nginx

#方法1
[root@admin nginx]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
#方法2
[root@admin nginx]# cd /usr/local/nginx/sbin
[root@admin sbin]# ./nginx

 

启动报错

使用ps ef|grep nginx,并未发现有nginx进程,有可能被其他进程占用,这时可以采用如下方式处理:

 查看80端口占用

netstat -ntpl

杀掉占用80端口的进程

kill -9 pid

written by ocean

7月 15

Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。 

要使用MEF 需要添加 System.ComponentModel.Composition.dll 的引用, 

然后导入命名空间:

using System.ComponentModel.Composition; 
using System.ComponentModel.Composition.Hosting;

MEF提供了两个关键字

Export:哪个类可以被用来Compose,也就是说这个类是不是可以用来填充的实现类,所以Export标记的是类,而不是具体的某个对象。

Import:哪个对象需要Compose。也就是需要被实现类给填充,所以Import标记的是对象,一般该对象是接口,因为如果是具体类的话,那就不需要Import了

实例如下

创建接口

    public interface IUser
    {
        void Show(string msg);
    }

接口实现类,注意Export关键字,说明该类是可以被用来Compose的

    [Export(typeof(IUser))]
    public class User : IUser
    {
        public void Show(string msg)
        {
            Console.WriteLine("来自User类,"+ msg);
        }
    }

调用类,注意初始化方法里面需要预先处理,否则user对象会成为null

    public class TestClass
    {
        [Import(typeof(IUser))]
        public IUser user { get; set; } 

        public void Test()
        { 
            user.Show("我是test");
        }


        public TestClass()
        {
            var catalog = new AggregateCatalog();
            CompositionContainer _container;
            catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);
            _container.ComposeParts(this);
        }
    }

如果有多个类实现了IUser接口,可以使用ImportMany关键字,结果为IEnumerable<IUser>对象

还可以使用下面的构造方法指定特别的实现类

        [Import("userXXX", typeof(IUser))]
        public IUser user { get; set; }

written by ocean

7月 15

之前一直有看到过Emit,一直没有下定决心学一下,昨天的Dapper很好用,想学习的话呢需要先理解Emit,刚好就算做学习储备了,写个学习笔记先

简单入门,从网上找的

如果只是想要创建一个Dynamic Method 那么可以直接使用HelloWorld例子中使用的DynamicMethod类来创建一个动态方法,并在构造函数时传入它所依附的类或者模块

        /// <summary>
        /// 用来调用动态方法的委托
        /// </summary>
        private delegate void HelloWorldDelegate(); 
        static void Main(string[] args)
        { 
            //定义一个名为HelloWorld的动态方法,没有返回值,没有参数
            DynamicMethod helloWorldMethod = new DynamicMethod("HelloWorld", null, null);

            //创建一个MSIL生成器,为动态方法生成代码
            ILGenerator helloWorldIL = helloWorldMethod.GetILGenerator();

            //将要输出的Hello World!字符创加载到堆栈上
            helloWorldIL.Emit(OpCodes.Ldstr, "blog.wx6.org");
            //调用Console.WriteLine(string)方法输出Hello World!
            helloWorldIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
            //方法结束,返回
            helloWorldIL.Emit(OpCodes.Ret);

            //完成动态方法的创建,并且获取一个可以执行该动态方法的委托
            HelloWorldDelegate HelloWorld = (HelloWorldDelegate)helloWorldMethod.CreateDelegate(typeof(HelloWorldDelegate));

            //执行动态方法,将在屏幕上打印Hello World!
            HelloWorld(); 

            Console.Read(); 
        }

使用Emit一般包括以下步骤:

1)        创建一个新的程序集(可以选择存在与内存中或者持久化到硬盘);

2)        在程序集内创建一个模块;

3)        在模块内创建动态类;

4)        给动态类添加动态方法、属性、事件,等;

5)        生成相关的IL代码;

6)        返回创建出来的类型或持久化到硬盘中。

string name = "EmitExamples.DynamicFibonacci";
string asmFileName = name + ".dll";

#region Step 1 构建程序集 
//创建程序集名
AssemblyName asmName = new AssemblyName(name); 
//获取程序集所在的应用程序域
//你也可以选择用AppDomain.CreateDomain方法创建一个新的应用程序域
//这里选择当前的应用程序域
AppDomain domain = AppDomain.CurrentDomain; 
//实例化一个AssemblyBuilder对象来实现动态程序集的构建
AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); 
#endregion

#region Step 2 定义模块 
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, asmFileName); 
#endregion

#region Step 3 定义类型 
TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); 
#endregion

#region Step 4 定义方法 
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
    "Calc",
    MethodAttributes.Public,
    typeof(Int32),
    new Type[] { typeof(Int32) }); 
#endregion

#region Step 5 实现方法 
ILGenerator calcIL = methodBuilder.GetILGenerator();  
//定义标签lbReturn1,用来设置返回值为1
Label lbReturn1 = calcIL.DefineLabel();
//定义标签lbReturnResutl,用来返回最终结果
Label lbReturnResutl = calcIL.DefineLabel(); 
//加载参数1,和整数1,相比较,如果相等则设置返回值为1
calcIL.Emit(OpCodes.Ldarg_1);
calcIL.Emit(OpCodes.Ldc_I4_1);
calcIL.Emit(OpCodes.Beq_S, lbReturn1); 
//加载参数1,和整数2,相比较,如果相等则设置返回值为1
calcIL.Emit(OpCodes.Ldarg_1);
calcIL.Emit(OpCodes.Ldc_I4_2);
calcIL.Emit(OpCodes.Beq_S, lbReturn1); 
//加载参数0和1,将参数1减去1,递归调用自身
calcIL.Emit(OpCodes.Ldarg_0);
calcIL.Emit(OpCodes.Ldarg_1);
calcIL.Emit(OpCodes.Ldc_I4_1);
calcIL.Emit(OpCodes.Sub);
calcIL.Emit(OpCodes.Call, methodBuilder); 
//加载参数0和1,将参数1减去2,递归调用自身
calcIL.Emit(OpCodes.Ldarg_0);
calcIL.Emit(OpCodes.Ldarg_1);
calcIL.Emit(OpCodes.Ldc_I4_2);
calcIL.Emit(OpCodes.Sub);
calcIL.Emit(OpCodes.Call, methodBuilder); 
//将递归调用的结果相加,并返回
calcIL.Emit(OpCodes.Add);
calcIL.Emit(OpCodes.Br, lbReturnResutl); 
//在这里创建标签lbReturn1
calcIL.MarkLabel(lbReturn1);
calcIL.Emit(OpCodes.Ldc_I4_1); 
//在这里创建标签lbReturnResutl
calcIL.MarkLabel(lbReturnResutl);
calcIL.Emit(OpCodes.Ret); 
#endregion

#region Step 6 收获 
Type type = typeBuilder.CreateType(); 
assemblyBuilder.Save(asmFileName); 
object ob = Activator.CreateInstance(type); 
for (int i = 1; i < 10; i++)
{
    Console.WriteLine(type.GetMethod("Calc").Invoke(ob, new object[] { i }));
} 
#endregion

原文链接  http://www.cnblogs.com/yingql/archive/2009/03/20/1418007.html

written by ocean

7月 14

开发环境基于最新版python3.4,实际例子发现和python2.x有很多的不同

开发工具使用 IDLE  (python自带)

 

 输出命令

print ('blog.wx6.org')

 输出表达式

length = 5
breadth = 2
area = length * breadth
print ('Area is', area)
print ('Perimeter is', 2 * (length + breadth) ) 

>>> 
Area is 10
Perimeter is 14

 

if条件选择

number = 23
guess = int(input('Enter an integer : '))
if guess == number:
    print ('Congratulations, you guessed it.') # New block starts here
    print ("but you do not win any prizes!") # New block ends here
elif guess < number:
    print ('No, it is a little higher than that') # Another block
    # You can do whatever you want in a block ...
else:
    print ('No, it is a little lower than that') 
    # you must have guess > number to reach here
print ('Done')
# This last statement is always executed, after the if statement is executed

 

for循环,三个参数,起始,截止,步长 

for i in range(1,10,2):
    print(i)
else:
    print("done")
>>> 
1
3
5
7
9
done

 

定义函数

def hello():
    print("hello")
    print("world")
hello()  #call function

def Max(a,b):
    if a>b:
        print(a);
    else:
        print(b); 
x=10
y=100
Max(x,y)

 

 Gloabl

def test():
    global x
    print ("x is ",x)
    x=2
    print("changed local x is ",x)
x=50
test()
print("value of x is ",x);

默认参数

def say(message, times = 1):
    print (message * times )
say('Hello')
say('World', 5)

 

 

 学习进度

http://sebug.net/paper/python/ch08.html

 

python学习教程

written by ocean

7月 14

假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM. 点击下载 Dapper的优势:

1,Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll.

2,Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。

3,Dapper支持什么数据库。Dapper支持Mysql,SqlLite,Mssql2000,Mssql2005,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db

4,Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。 5,Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高高高。

 

下载地址 https://github.com/StackExchange/dapper-dot-net 

测试的数据结构为

    public class ReportInfo{
        public string UserName { get; set; }
        public string DataString { get; set; }
        public int ProjectCode { get; set; }
        public int Hour { get; set; }
    }

 

Dapper以扩展IDbConnection类的方式 提供三个扩展方法重载

 

第一种

public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

调用示例

            using (IDbConnection connection = new SqlConnection(ConnectionString)) {
                var list = connection.Query<ReportInfo>("select * from Report where UserName=@UserName ",
                    new { UserName = "Ocean" });
            }

 

第二种

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

调用示例

            using (IDbConnection connection = new SqlConnection(ConnectionString)) {
                var list = connection.Query("select * from Report where UserName=@UserName ",
                    new { UserName = "Ocean" });

                foreach (var item in list)
                {
                    Console.WriteLine(item.UserName);
                } 
            }

 

第三种

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)

调用示例

            using (IDbConnection connection = new SqlConnection(ConnectionString))
            {
                var result = connection.Execute(@"insert Report(UserName, DataString,ProjectCode,Hour) values (@UserName, @DataString,@ProjectCode,@Hour)",
                      new { UserName = "OceanTest", DataString = "blog.wx6.org", ProjectCode = 1, Hour = 100 });
            }

entity的话可以更简单

        public static void Insert(BookInfo bookInfo)
        {
            using (IDbConnection connection = new MySqlConnection(Config.ConnectionString))
            {
                var result = connection.Execute(@"insert tb_book(Title,Content,Volume) values (?Title,?Content,?Volume)",
                                                bookInfo);
            }
        }

另外还可以批量添加

            using (IDbConnection connection = new SqlConnection(ConnectionString))
            {
                var result = connection.Execute(@"insert Report(UserName, DataString,ProjectCode,Hour) values (@UserName, @DataString,@ProjectCode,@Hour)",
                      new []{
                      new { UserName = "OceanTest2", DataString = "blog.wx6.org", ProjectCode = 1, Hour = 100 },
                      new { UserName = "OceanTest3", DataString = "blog.wx6.org", ProjectCode = 1, Hour = 100 },
                      new { UserName = "OceanTest4", DataString = "blog.wx6.org", ProjectCode = 1, Hour = 100 }
                      });
            }

 

多结果集,需要注意结果集大于1条数据则Single()会报错

            using (IDbConnection connection = new SqlConnection(ConnectionString))
            { 
                var sql = @"
                            select * from Report where UserName=@UserName;
                            select * from Report where ProjectCode=@ProjectCode;
                            select * from [User] where UserName=@UserName ;
                            select * from Report where Hour>@Hour";

                using (var multi = connection.QueryMultiple(sql,
                            new { UserName = "Ocean", ProjectCode = 3, Hour=100 }))
                {
                    var recordSet1 = multi.Read<ReportInfo>().ToList();
                    var recordSet2 = multi.Read<ReportInfo>().Single();
                    var recordSet3 = multi.Read<UserInfo>().ToList();
                    var recordSet4 = multi.Read<ReportInfo>().ToList();
                } 
            }

 

支持事务(未验证)

            using (IDbConnection connection = new SqlConnection(ConnectionString))
            {
                const string deleteColumn = "delete from [Column] where ColumnCatid=@catid";
                const string deleteColumnCat = "delete from ColumnCat where id=@Id";

                IDbTransaction transaction = connection.BeginTransaction();
                int row = connection.Execute(deleteColumn, new { catid = 1}, transaction, null, null);
                row += connection.Execute(deleteColumnCat, new { id = 1 }, transaction, null, null);
                transaction.Commit(); 
            }

 

另外一种批量插入数据的方法(未测试)

    //批量插入数据
    List<School> schools = new List<School>()
    {      
            new School() {Address="China·BeiJing",Title="清华大学" },      
            new School() {Address="杭州",Title="浙江大学" },      
            new School() {Address="不知道,US?",Title="哈弗大学" }
    };    
    //在执行参数化的SQL时,SQL中的参数(如@title可以和数据表中的字段不一致,但要和实体类型的属性Title相对应)
    dbConnection.Execute("insert into t_schools(Address,Name) values(@address,@title);", schools);

     

 总结

Dapper通过Emit的方式组装语句,因此执行效率接近原生语句.

并且很轻,无配置,无属性.SQL语句完全可控,简直就是我最喜欢的东西啊.

相见恨晚,以后在项目中需要多用此ROM类库

written by ocean \\ tags:

7月 11

大约在一个月之前申请了免费的京东云,还参加了一个微博转发的活动,升为4g内存了。

然后就非常想把自己的博客跑到云上面。

可惜目前免费的京东云只支持php,java,python等语言,没有我喜欢的.net

于是就有了移植的念头

旧的博客是C#+Access的,生成静态html

在京东云支持的几种语言中选择了java,毕竟这个还是相对熟悉的。

于是装了eclipse,mysql就吭哧吭哧的开始了。

期间遇到坑无数。

git很容易就学会可以使用了

但是京东只支持maven的项目,在maven转换的时候出现了错误,网上所有的能解决的方法对我都无效。找了一位资深java开发的朋友也花了一两天时间都没解决掉,一度想到放弃。但是成功往往就是在再坚持一下,也许距离你放弃的地方再努力一下就可以成功了,终于解决这个问题了。

然后还遇到Mysql乱码的问题,因为云数据库本地连接不上,只能通过改代码,commit,push,发布,效率很低,很慢,但是终于还是解决了。

然后就是真正的开发了。ibatis+jsp+urlrewrite

java里的各种框架各种配置,不会了就百度一下,相较于.net,java里的这种问题网络上问的很多,答得也很多,确实很方便。

最明显的一个,html截取并且补齐htmltag,我记得之前.net的那个当时找了很多代码都不太合适,后来自己写的,可是java的一搜索马上就有现成的代码。

历时三天,终于把博客从.net改为java的了

并且做了一个简单的后台,以后再也不用手工上传html了。

第一次写这么长的非技术类blog,这是来自云上的第一篇文章

written by ocean