一,原理

首先,我们要明白Git是什么,它是一个管理工具或软件,用来管理什么的呢?当然是在软件开发过程中管理软件或者文件的不同版本的工具,一些作家也可以用这个管理自己创作的文本文件,由Linus开发的,也是Linux系统开发所用到的分布式版本控制软件。一说到分布式,其实就是每个电脑都有这么个版本库,而摒弃了传统的中心文件系统服务,所以每个人都能保存、还原之前的版本。在航天二院实习的时候,mentor让我改一个软件的Bug,由于国企没有外网,所以不能用github,院里面也没有搭建自己的Git文件服务器,所以每次改Bug之前都要备份一个之前的版本,以日期命名,而且后面还容易忘记那个版本有哪些功能模块,就我们两个人开发一个软件都把版本搞错了好几次,真心头痛。

二,Git常用命令

git的常用命令有:init、add、rm、mv、commit、push、pull、clone、log、checkout、megre、status、branch、diff、config、remote、fetch、reset、tag、show、stash、grep、rebase、gc等。

1,本地操作

Git命令 解释 撒旦法备注
git init 初始化Git环境 先cd到要管理的文件夹中
git add *.txt / . 添加文件到暂存区 . 是将所有文件都添加到暂存区
git status 查看文件的状态  
git commit -m 'First commit' 提交更新到版本库 -m 是message的缩写,即每次添加更新的备注
git log 查看提交更新的记录  
git rm *.txt 删除文件  
git mv a.txt b.txt 修改文件名 将a.txt的文件名改为b.txt

2,远程操作

Git命令 解释 撒旦法备注
git config --global user.name "your name" 设置username,因为github每次commit都会记录他们 github注册时的用户名
git config --global user.email "your_email@youremail.com" 设置email github注册时的邮箱地址
git remote add origin https://...git 查看文件的状态与Github建立远程连接 现在github网站上建立仓库
git push -u origin master 提交推送到Github的仓库中 master分支可以是其他分支
   

在远程操作Github之前要进行ssh key的配置,网上有很多教程可以参考。大概分三步:

  • 在本地创建ssh key,$ ssh-keygen -t rsa -C "your_email@youremail.com" (github网站上注册的邮箱),回车后会在当前用户.ssh文件夹下生成id_rsa、id_rsa.pub、known_hosts三个文件

  • 打开id_rsa.pub,复制里面的key, 回到github网站,进入Account Settings,左边选择SSH Keys,Add SSH Key, Title随便填,粘贴key。

  • 验证是否成功,在本地git bash下输入,$ ssh -T git@github.com ,回车就会看到:You’ve successfully authenticated, but GitHub does not provide shell access 。这就表示已成功连上github。

参考链接:

git中sshkey有何作用?

http://www.bootcss.com/p/git-guide/

Git命令脑图(图片来自Github)

3,Git分支管理模型Pic

三,Demo

1,初始化一个git仓库,新建一个code.txt文件,提交到git版本库,现在git开始管理code.txt文件了

 
ckjbug@ckjbug MINGW64 ~/Desktop

$ mkdir gituse

ckjbug@ckjbug MINGW64 ~/Desktop

$ cd gituse

ckjbug@ckjbug MINGW64 ~/Desktop/gituse

$ git init

Initialized empty Git repository in C:/Users/Enz/Desktop/gituse/.git/

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

No commits yet

Untracked files:

  (use "git add <file>..." to include in what will be committed)

code.txt

nothing added to commit but untracked files present (use "git add" to track)

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git add code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

No commits yet

Changes to be committed:

  (use "git rm --cached <file>..." to unstage)

new file:   code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git commit -m 'First commit'

[master (root-commit) 0f67f2c] First commit

 1 file changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

nothing to commit, working tree clean
 

2,修改文件,在code.txt添加一行代码,然后用checkout回到修改前(即没有添加代码前的版本,这里之前写入的代码没有了,空文本),这只是checkout的一种用法,更多是后面学习的git的分支转换。

 
ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git checkout -- <file>..." to discard changes in working directory)

modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout -- code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ notepad code.txt
 

3,还是上面这个功能,回到文本修改前的状态,但是我们修改文件后已经添加到暂存区了,这时使用git checkout code.txt已经没用了,可以用git reset回到没有添加到暂存区的状态(最初始的状态)

 
ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ clear

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git checkout -- <file>..." to discard changes in working directory)

modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git add code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git reset

Unstaged changes after reset:

M       code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git checkout -- <file>..." to discard changes in working directory)

modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout -- code.txt
 

4,添加、切换、删除分支(添加develop开发者的工作分支)

 
ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch

* master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch develop

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch

  develop

* master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout develop

Switched to branch 'develop'

M       code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git branch

* develop

  master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git checkout master

Switched to branch 'master'

M       code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch

  develop

* master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch -d develop

Deleted branch develop (was 0f67f2c).

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch

* master
 

5,新建一个开发者develop分支,然后添加develop.txt文本,添加到暂存库,提交,最后转换到master分支,发现develop.txt文本不见了,这就是版本管理,每个分支控制一个版本,当我们转回到develop分支下时这个devel.txt文件又出现了。如果我们在develop分支下修改了master分支的code.txt,当我们转换为master分支上时,不会出现develop分支下的修改。

 
ckjbug@ckjbug MINGW64 ~/Desktop/gituse

$ git init

Initialized empty Git repository in C:/Users/Enz/Desktop/gituse/.git/

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

No commits yet

Untracked files:

  (use "git add <file>..." to include in what will be committed)

code.txt

nothing added to commit but untracked files present (use "git add" to track)

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git add .

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

No commits yet

Changes to be committed:

  (use "git rm --cached <file>..." to unstage)

new file:   code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git commit -m 'First commit'

[master (root-commit) 2571887] First commit

 1 file changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git status

On branch master

nothing to commit, working tree clean

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch

* master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git branch develop

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout develop  //之后添加一个develop.txt文件

Switched to branch 'develop'

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git branch

* develop

  master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git status

On branch develop

Untracked files:

  (use "git add <file>..." to include in what will be committed)

develop.txt

nothing added to commit but untracked files present (use "git add" to track)

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git add develop.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git commit -m 'add a develop_txt on branch develop'

[develop 2fd0d60] add a develop_txt on branch develop

 1 file changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 develop.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git branch

* develop

  master

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git checkout master

Switched to branch 'master'

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git checkout develop  //在develop分支下修改master分支下的code.txt文件

Switched to branch 'develop'

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git status

On branch develop

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git checkout -- <file>..." to discard changes in working directory)

modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git add code.txt

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git commit -m '在develop分支下修改了master分支的code.txt文件'

[develop 903c8e0] 在develop分支下修改了master分支的code.txt文件

 1 file changed, 1 insertion(+)

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git status

On branch develop

nothing to commit, working tree clean

ckjbug@ckjbug MINGW64 ~/Desktop/gituse (develop)

$ git checkout master   //此时code.txt修改的代码不在了

Switched to branch 'master'
 

6,融合分支,在master分支上时,将develop分支merge到master分支上。这时develop.txt文件出现了。即融合到了master分支中。

 
ckjbug@ckjbug MINGW64 ~/Desktop/gituse (master)

$ git merge develop

Updating 2571887..903c8e0

Fast-forward

 code.txt    | 1 +

 develop.txt | 0

 2 files changed, 1 insertion(+)

 create mode 100644 develop.txt
 

7,Merge时冲突的处理,加入两个不同分支同时修改了主分支下code.txt中的第三行代码,两个分支在融合时会冲突。

解决冲突的参考链接:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001375840202368c74be33fbd884e71b570f2cc3c0d1dcf000

8,远程推送push、拉取pull项目代码,在实际项目中,往往已经存在了远程的项目,当你参与到项目的开发当中时,

如果我们将一个Github已经存在的项目clone下来,然后修改后与远程仓库连接,出现这样的错误:fatal: remote origin already exists. 则可以输入 git remote rm origin后从新建立连接。
参考链接:

https://blog.csdn.net/weijinqian0/article/details/76217014

相关链接:

在线教程【廖雪峰】

知乎

__EOF__

作  者:ckjbug
出  处:https://www.cnblogs.com/ckjbug/p/9761302.html
关于博主:编程路上的小学生,热爱技术,喜欢专研。评论和私信会在第一时间回复。或者直接私信我。
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!

Asp.net生命周期与Http协议

 

Http协议,底层的东西还是不是特别熟悉,感觉要经过沉淀之后才能理解这些东西吧

1.Asp.net生命周期

Asp.net生命周期:

从发起请求开始,到IIS进行处理的全部过程,然后再到获取结果

当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给ASPNET_ISAPI.dll,ASPNET_ISAPI.dll会通过http管道(Http PipeLine)将请求发送给ASPNET_WP.exe进程,在ASPNET_WP.exe进程中通过HttpRuntime来处理这个请求,处理完毕将结果返回客户端。     inetinfo.exe进程:是www服务的进程,IIS服务和ASPNET_ISAPI.DLL都寄存在此进程中。     ASPNET_ISAPI.DLL:是处理.aspx文件的win32组件。其实IIS服务器是只能识别.html文件的,当IIS服务器发现被请求的文件是.aspx文件时,IIS服务器将其交给aspnet_isapi.dll来处理。     aspnet_wp.exe进程:ASP.NET框架进程,提供.net运行的托管环境,.net的CLR(公共语言运行时)就是寄存在此进程中。

ASP.NET Framework处理一个Http Request的流程:     HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
ASP.NET请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET把http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给客户端。我们可以在每个HttpModule中都可以干预请求的处理过程。

2.Htpp协议的生命周期

这个感觉要后续继续加深理解之后再进行补充吧,目前就拿别人的思路来解答这个过程

1.输入url,浏览器DNS解析域名,获取ip

2.三次握手,建立tcp链接

3.向服务端发送http请求

4.服务端处理请求并响应

5.浏览器渲染HTML

6在渲染的过程中继续加载css,js,图片,音频,视频文件

7 呈现给用户

托管代码与非托管代码的区别

 

其实是知道这个东西,但是不知道专业术语居然叫这个,我以为是Azure云托管,好吧,开个玩笑

不止C#,java也是托管代码啊,重点,重点,重点!!!

1.简单的说,就是代码被编译成MSIL后在.net的Framework下运行,同操作系统底层的交互都交给framework去做。所谓非托管代码就是脱离了Framework的管制,

直接同底层API打交道,自己管理自己的内存和安全机制等东西。而托管代码就不管这些,全都由Framework去完成

2.“程序”一般都是在对操作系统进行直接或者间接的操作
“托管程序”是需要通过访问公共语言运行时(cls)才能访问操作系统的程序
而“非托管程序”不用通过访问公共语言运行时(cls)可以直接访问操作系统的程序

3.vb.net,C#等写的程序是托管程序,VC++可以写托管程序,如果用到了内存管理,则只能编译为非托管程序这些东西MSDN都有描述

通过IEnumerable接口遍历数据

 

使用IEnumerable接口遍历数据,这在项目中会经常的用到,这个类型呢主要是一个枚举器。

1.首先需要让该类型实现一个名字叫IEnumerable的接口,实现该接口的主要目的是为了让当前类型中增加一个名字叫GetEnumerator()的方法。

public class Person : IEnumerable
    {
        private string[] Friends = new string[] { "张三", "李四", "王五", "赵六" };

        public string Name
        {
            get;
            set;
        }
        public int Age
        {
            get;
            set;
        }
        public string Email
        {
            get;
            set;
        }

        #region IEnumerable 成员

        //这个方法的作用就是返回一个“枚举器”
        public IEnumerator GetEnumerator()
        {
            return new PersonEnumerator(this.Friends);
        }

        #endregion
    }

2.希望一个类型被枚举遍历,就是要实现一个枚举器方法

public class PersonEnumerator : IEnumerator
    {
        public PersonEnumerator(string[] fs)
        {
            _friends = fs;
        }
        private string[] _friends;

        //一般下标都是一开始指向了第一条的前一条。第一条是0
        private int index = -1;

        #region IEnumerator 成员

        public object Current
        {
            get
            {
                if (index >= 0 && index < _friends.Length)  //下标有范围
                {
                    return _friends[index];
                }
                else
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }

        public bool MoveNext()
        {
            if (index + 1 < _friends.Length)     //下标有范围
            {
                index++;
                return true;
            }
            return false;
        }

        public void Reset()
        {
            index = -1;
        }

        #endregion
    }

3.然后进行遍历,这里呢可以调用自己封装的MoveNext方法去找数组元素

 Person p = new Person();

            IEnumerator etor = p.GetEnumerator();
            while (etor.MoveNext())
            {
                Console.WriteLine(etor.Current.ToString());
            }

也可以直接使用foreach,而且主要是因为是枚举元素,类似与数组,list等等之类的,都可以使用Lambda表达式来进行数据的处理

 Person p = new Person();
            foreach (string item in p)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("ok");

4.输出的结果如下:

依赖注入与控制反转

 

反正这个概念我一般都是不去记得,首先看一下什么是依赖:

有一个类是Animal,然后我定义了一个BlackCat类,类里面有一个BlackCat方法,那么这里的BlackCat就依赖Animal

public class BlackCat
{
     public BlackCat(Animal  Cat)
     {
          Cry();
     }
}

BlackCat类实例化的时候需要一个Animal的对象作为构造函数的参数,那么BlackCat就依赖Animal,这就叫依赖

当然,不用构造函数的方式,在BlackCat类内部去new一个Animal,也是依赖;当然注入的话,就像是你写了一个类,然后

通过IOC框架,把这个类注入到其他类中,这就是注入

           控制反转的意思就好理解了,就比如我定义了一个类,类里面有一个方法,然后我现在要把这个方法的控制权交给别人来使用,这就是控制反转。

在编写代码的时候,我们需要把一些接口编写成通用的道理就在这里了,便于做到代码复用

下面即以猫的例子来进行解说控制反转

1.先定义一个动物类

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOC
{
    class Animal
    {
        public void Cry()
        {
            Console.Write("动物喊叫");
        }
    }
}

2.定义一个猫的类

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOC
{
    class Cat:Animal
    {
        public void Cry()
        {
            Console.WriteLine("动物喊叫");
        }
    }
}

3.我用实例化一个动物类,然后查看结果

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOC
{
    class Program
    {
        static void Main(string[] args)
        {
            Animal A = new Cat();
            A.Cry();
            Console.ReadLine();
        }
    }
}

4.可以看到我用子类可以替换掉父类,也可以用父类替换掉子类,其实并没有太大的影响

Animal A = new Cat();

可以看见输出结果如下

C#多线程——优先级

 

在我的公司这里,因为要跟很多特殊的设备打交道,所以会用到多线程的东西,那么我们在进行多线程处理的时候,怎么去设置优先级

我这里用听歌和下载小说做了个例子,我们用电脑的时候肯定是可以边听歌边下载小说的,那么这就需要并行,有个问题就是我想优先听

歌,下载小说对我来说不是那么急的话我就可以对两个事情进行优先级的管控。

线程里有个属性Priority可以用来设置优先级,我设置线程1的优先级高于线程2的优先级,那么线程1就会比线程2多运行一段时间,这个是人眼观察不出来的

运行速度,CPU运行速度可不是能用人眼查看的

            bool b = true;
            int i=0, j=0;
            string Song = "";
            string Download = "";
            Thread Thread1=new Thread(() =>
            {
                while (b)
                {
                    Song="一百万个可能";
                    i++;

                }
            })
            {
                Name = "Thread1",
                Priority = ThreadPriority.Highest
            };
             Thread Thread2=new Thread(() =>
            {
                while (b)
                {
                    Download = "小说三体";
                    j++;
                }
            })
            {
                Name = "Thread2",
                Priority = ThreadPriority.Lowest
            };
            Thread1.Start();
            Thread2.Start();
            Thread.Sleep(1000);
            b = false;
            Console.WriteLine("Song: {0}, Download: {1}", Song, Download);
            Console.WriteLine("歌曲的优先级:{0}",i);
            Console.WriteLine("下载的优先级:{0}",j);
            Console.ReadLine();

这里我们看一下执行结果

从结果中可以看到,优先级高的线程得到运行的次数比优先级低的线程多,但即使是最低优先级的线程都有很大的机会来执行。

AutoFac容器初步

 

转载请注明出处,AutoFac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

那么我们怎么来使用这样一个框架呢

1、在引用项右击,选择Nuget管理,这里我们要导入两个包

一个是AutoFac包,另外一个就是Autofac ASP.NET MVC5 Intergration

在webapi里面使用的话我们需要添加一个Autofac ASP.NET Web API2.2 Intergration 才可以。

2.Global.asax.cs属性注入,配置IOC容器,我这里配置的是通用的以I开头的Repository(仓库类)

#region autofac IOC容器配置
            var builder = new ContainerBuilder();

            //注册所有的controller
            builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
            //注册所有模块module
            builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());

            var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();

            //注册所有继承IDependency接口的类
            builder.RegisterAssemblyTypes(assemblys)
            .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);

            //注册服务,所有IxxxxRepository=>xxxxRepository
            builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();

            var container = builder.Build();

            BaseInfo._container = container;

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            #endregion

3.新建实体基类以及实体类,也就是创建数据模型

base类:

public class BaseEntity
    {
        [NotMapped]
        [PropertyModelBinder("start")]
        public int pageIndex { get; set; }

        [NotMapped]
        [PropertyModelBinder("length")]
        public int pageSize { get; set; }

        [NotMapped]
        public string draw { get; set; }

        [NotMapped]
        public List<Orderby> order { get; set; }

        [NotMapped]
        public List<Datacolumn> columns { get; set; }

    }

   public class Orderby {
       public string column { get; set; }

       public string dir { get; set; }
   }

   public class Datacolumn {
       public string data { get; set; }

       public string name { get; set; }

       public bool searchable { get; set; }

       public bool orderable { get; set; }
   }

实体类:

public class User : BaseEntity
    {
       public User() {
           RoleList = new List<Role>();
           MessageList = new List<UserMappingMessage>();
       }
       public int UserID { get; set; }

       public string UserName { get; set; }

       public string UserPassword {get;set;}

       public string UserReallyname {get;set;}

       public string HeadPortrait { get; set; }

       public string MobilePhone { get; set; }

       public string Email { get; set; }

       public int DepartmentID {get;set;}

       public bool IsEnable {get;set;}

       public DateTime CreateTime {get;set;}

       public DateTime? UpdateTime {get;set;}

       public string Remark { get; set; }

       public ICollection<Role> RoleList { get; set; }

       //接收消息列表
       public ICollection<UserMappingMessage> MessageList { get; set; }

       public Dictionary Department { get; set; }

       //发送消息列表
       public List<Message> Messages { get; set; }

    }

4.创建仓储接口,因为我在配置Global属性时,已经说明了我要注入所有以 “I” 开头的接口,那么我就把这个用户的接口给定义为IUserRepository

当然,不同的实体类所需要的仓储接口也不一样,这里根据自己的实际需求去写需要的方法类,接口嘛,就不要在这里具体实现你的方法了

 public interface IUserRepository
    {
        Tuple<int,List<User>> GetList(User model);

        List<User> GetUserInfos();

        User GetSingle(User model);

        User GetbyID(int userID);

        void AddUser(User model);

        void ModifyUser(User model);

        void DeleteUser(User model);

        void SetUserInfoRole(int userID, List<int> roleIDList);

        List<AutoUserDo> GetUserInfobyName(string value);

        void ResetUserPWDbyID(int id);

    }

5.我们定义一个实现接口的类,然后把接口的方法给实现,这里面就是对数据实体进行操作了

public class UserRepository : IUserRepository
    { 

        public Tuple<int, List<User>> GetList(User model)
        {
            using (UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>())
            {
                var SysUserRepository = dal.GetRepository<User>();

                var conditions = ExpandHelper.True<User>();
                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And(a => a.UserName.Contains(model.UserName));

                if (!string.IsNullOrEmpty(model.UserReallyname))
                    conditions = conditions.And(a => a.UserReallyname.Contains(model.UserReallyname));

                if (model.DepartmentID > 0)
                    conditions = conditions.And(a => a.DepartmentID == model.DepartmentID);

                var templist = SysUserRepository.Get(filter: conditions, includeProperties: "RoleList");

                var count = templist.Count();

                if (model.order != null&&model.order.Count()>0)
                {
                    foreach (var item in model.order)
                    {
                        var column = model.columns.ElementAt(int.Parse(item.column));
                        templist = templist.OrderSort(column.data, item.dir);
                    }

                }
                var result = templist.PageBy(model.pageIndex, model.pageSize).ToList();

                return new Tuple<int, List<User>>(count, result);
            }
        }

        public User GetSingle(User model)
        {
            using(UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>()){

                var conditions = ExpandHelper.True<User>();

                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And( a => a.UserName == model.UserName || a.MobilePhone == model.UserName);
                if (!string.IsNullOrEmpty(model.MobilePhone))
                    conditions = conditions.And(a => a.MobilePhone == model.MobilePhone);

                var result = dal.GetRepository<User>().Get(conditions).FirstOrDefault();
                return result;
            }
        }

        public User GetbyID(int userID)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

              //  var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID, includeProperties: "RoleList.MenuList,RoleList.rbList").AsNoTracking().FirstOrDefault();

                var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID,includeProperties: "RoleList").FirstOrDefault();

                foreach (var item in result.RoleList)
                {
                    var role=dal.GetRepository<Role>().Get(a=>a.RoleID==item.RoleID,includeProperties:"MenuList,rbList").FirstOrDefault();
                    item.MenuList = role.MenuList;
                    item.rbList = role.rbList;
                } 

                return result;
            }
        }

        public void AddUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                dal.GetRepository<User>().Insert(model);
                dal.Save();
            }
        }

        public void ModifyUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                dal.GetRepository<User>().UpdateSup(model, new List<string>() { "IsEnable", "CreateTime" }, false);
                dal.Save();
            }
        }

        public void DeleteUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
               var sysUserRepository= dal.GetRepository<User>();
               var Usermodel = sysUserRepository.GetByID(model.UserID);
               Usermodel.IsEnable=Usermodel.IsEnable?false:true;
               sysUserRepository.UpdateSup(Usermodel, new List<string>() { "IsEnable" });
               dal.Save();
            }
        }

        /// <summary>
        /// 添加用户角色信息,先删除原有数据,在添加到数据库
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="roleIDList"></param>
        /// <returns></returns>
        public void SetUserInfoRole(int userID, List<int> roleIDList)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                var sysUserRepository = dal.GetRepository<User>();
                var roleRepository = dal.GetRepository<Role>();
                var UserModel = GetbyID(userID);
                var roleList = UserModel.RoleList.ToList();

                roleList.ForEach(m =>
                {
                    var userModel = sysUserRepository.Get(filter: a => a.UserID == userID, includeProperties: "RoleList").FirstOrDefault();
                    var roleModel = roleRepository.GetByID(m.RoleID);
                    userModel.RoleList.Remove(roleModel);
                });

                roleIDList.ForEach(m =>
                {
                    var userModel = sysUserRepository.GetByID(userID);
                    var roleModel = roleRepository.GetByID(m);
                    userModel.RoleList.Add(roleModel);
                });

                dal.Save();
            }
        }

        public List<AutoUserDo> GetUserInfobyName(string value)
        {
            Mapper.Initialize(a =>
            {
                a.CreateMap<User, AutoUserDo>()
                 .ForMember(au => au.id, op => { op.MapFrom(user => user.UserID); })
                 .ForMember(au => au.text, op => { op.MapFrom(user => user.UserReallyname); })
                 .ForMember(au => au.department, op => { op.MapFrom(user => user.Department.DicValue); });
                a.CreateMap<Role, roleinfo>();
            });

            using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) {

                return dal.GetRepository<User>()
                          .Get(a => a.UserReallyname.Contains(value) || a.MobilePhone == value, includeProperties: "Department,Role").ProjectToQueryable<AutoUserDo>().ToList();

            }
        }

        public void ResetUserPWDbyID(int id)
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                var repository = dal.GetRepository<User>();
                var usermodel = new User()
                {
                    UserID = id,
                    UserPassword = "123456"
                };
                repository.UpdateSup(usermodel, new List<string>() { "UserPassword" });
                dal.Save();
            }
        }

        public List<User> GetUserInfos()
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                return dal.GetRepository<User>().Get().ToList();
            }
        }
    }

6.然后我们就可以在MVC的控制器里面去调用这些方法来实现我们所想要的功能了,我这里只展示一个方法

public void SendEmailAsync(Message model)
        {
            Task.Run(() =>
            {
                try
                {
                    var reclist = string.Empty;
                    foreach (var item in model.RecUser.Split(','))
                    {
                        var userinfo = this.UserRepository.GetbyID(int.Parse(item));  //这里就调用了实现接口的那个类的方法,去验证用户的ID
                        if (!string.IsNullOrEmpty(userinfo.Email))
                        {
                            reclist += userinfo.Email + ",";
                        }
                    }
                    if (!string.IsNullOrEmpty(reclist))
                    {
                        reclist = reclist.Substring(0, reclist.Length - 1);
                        EmailHelper email = new EmailHelper(reclist, model.MessageTitle, model.MessageText);
                        email.Send();
                    }
                    model.SendEmailState = 2;
                    this.MessageServer.SetSendState(model);
                }catch(Exception ex){
                    new LogHelper().LogError("发送邮件异常" + ex);
                    model.SendEmailState = 3;
                    this.MessageServer.SetSendState(model);
                }
            });
        }

那么整个流程就是这样,看着别人写的那些博客里面的流程不是那么的全面,我这里就详细的把AutoFac的整个流程给梳理出来了,有不对的地方请及时指出

后面我会详细说明一下Unity IOC框架是如何使用的,这里我就不再叙述了

下面是两篇比较好的博文,我觉得比较有参考意义的,可以看一下,喜欢我发布的内容的可以关注我,后面还会有其他的干货和内容进行分享

.NET领域最为流行的IOC框架之一Autofac:https://www.cnblogs.com/yinrq/p/5381492.html

.NET Unity IOC框架使用实例:https://blog.csdn.net/chen_peng7/article/details/54896449

C#特性详解

 

特性(attribute)是被指定给某一声明的一则附加的声明性信息。

在C#中,有一个小的预定义特性集合。在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们的代码中如何使用预定义特性。

    

      

 1 using System;
 2 public class AnyClass
 3 {
 4     [Obsolete("Don't use Old method, use New method", true)]
 5     static void Old( ) { }
 6     static void New( ) { }
 7     public static void Main( )
 8     {
 9         Old( );
10     }
11 }

  我们先来看一下上面这个例子,在这个例子中我们使用了Obsolete特性,它标记了一个不应该再被使用的程序实体。第一个参数是一个字符串,它解释了为什么该实体是过时的以及应该用什么实体来代替它。实际上,你可以在这里写任何文本。第二个参数告诉编译器应该把使用这个过时的程序实体当作一种错误。它的默认值是false,也就是说编译器对此会产生一个警告。

  当我们尝试编译上面这段程序的时候,我们将会得到一个错误: 
  AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'

  开发定制特性(custom attributes)

  现在让我们来看看如何开发我们自己的特性。 
  首先我们要从System.Attribute派生出我们自己的特性类(一个从System.Attribute抽象类继承而来的类,不管是直接还是间接继承,都会成为一个特性类。特性类的声明定义了一种可以被放置在声明之上新的特性)。

1 using System; 2 public class HelpAttribute : Attribute 3 { 4 }

  不管你是否相信,我们已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像上面我们使用Obsolete attribute一样。

  

1 [Help()]
2 public class AnyClass
3 {
4 }

  注意:对一个特性类名使用Attribute后缀是一个惯例。然而,当我们把特性添加到一个程序实体,是否包括 Attribute后缀是我们的自由。编译器会首先在System.Attribute的派生类中查找被添加的特性类。如果没有找到,那么编译器会添加 Attribute后缀继续查找。

到目前为止,这个特性还没有起到什么作用。下面我们来添加些东西给它使它更有用些。

 1 using System;
 2 public class HelpAttribute : Attribute
 3 {
 4     public HelpAttribute(String Descrition_in)
 5     {
 6         this.description = Description_in;
 7     }
 8     protected String description;
 9     public String Description
10     {
11         get
12         {
13             return this.description;
14         }
15     }
16 }
17 [Help("this is a do-nothing class")]
18 public class AnyClass
19 {
20 }

在上面的例子中,我们给HelpAttribute特性类添加了一个属性并且在后续的部分中我们会在运行时环境中查寻它。

  定义或控制特性的使用

  AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。 
  AttributeUsage有三个属性,我们可以把它放置在定制属性前面。第一个属性是:

  ValidOn 
  通过这个属性,我们能够定义定制特性应该在何种程序实体前放置。一个属性可以被放置的所有程序实体在AttributeTargets enumerator中列出。通过OR操作我们可以把若干个AttributeTargets值组合起来。

  AllowMultiple 
  这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次。

  Inherited 
  我们可以使用这个属性来控制定制特性的继承规则。它标记了我们的特性能否被继承。

  下面让我们来做一些实际的东西。我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。

 1 using System;
 2 [AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
 3 Inherited = false ]
 4 public class HelpAttribute : Attribute
 5 {
 6     public HelpAttribute(String Description_in)
 7     {
 8         this.description = Description_in;
 9     }
10     protected String description;
11     public String Description
12     {
13         get
14         {
15             return this.description;
16         }
17     }
18 }

  先让我们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:

  

1 [Help("this is a do-nothing class")]
2 public class AnyClass
3 {
4     [Help("this is a do-nothing method")] //error
5     public void AnyMethod()
6     {
7     }
8 }

  编译器报告错误如下:
  AnyClass.cs: Attribute 'Help' is not valid on this declaration type. 
  It is valid on 'class' declarations only.

  我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:

  Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,Parameter,Delegate

All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate

  ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface

  下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。

1 [Help("this is a do-nothing class")]
2 [Help("it contains a do-nothing method")]
3 public class AnyClass
4 {
5     [Help("this is a do-nothing method")] //error
6     public void AnyMethod()
7     {
8     }
9 }

  它产生了一个编译期错误。 
  AnyClass.cs: Duplicate 'Help' attribute

  Ok,现在我们来讨论一下最后的这个属性。Inherited, 表明当特性被放置在一个基类上时,它能否被派生类所继承。

1 [Help("BaseClass")]
2 public class Base
3 {
4 }
5 public class Derive : Base
6 {
7 }

  这里会有四种可能的组合:

1 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
2 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
3 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
4 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ] 

  第一种情况:

  如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false。

  第二种情况:

  和第一种情况相同,因为inherited也被设置为false。

  第三种情况:

  为了解释第三种和第四种情况,我们先来给派生类添加点代码:

1 [Help("BaseClass")]
2 public class Base
3 {
4 }
5 [Help("DeriveClass")]
6 public class Derive : Base
7 {
8 }

  现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。

  第四种情况:

  在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true。

定义或控制特性的使用AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如何被使用。

属性和特性的区别可以参考一下: http://developer.51cto.com/art/200908/147097.htm

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Foxalien/archive/2009/12/05/4946672.aspx

C#特性详解

 

特性(attribute)是被指定给某一声明的一则附加的声明性信息。

在C#中,有一个小的预定义特性集合。在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们的代码中如何使用预定义特性。

    

      

 1 using System;
 2 public class AnyClass
 3 {
 4     [Obsolete("Don't use Old method, use New method", true)]
 5     static void Old( ) { }
 6     static void New( ) { }
 7     public static void Main( )
 8     {
 9         Old( );
10     }
11 }

  我们先来看一下上面这个例子,在这个例子中我们使用了Obsolete特性,它标记了一个不应该再被使用的程序实体。第一个参数是一个字符串,它解释了为什么该实体是过时的以及应该用什么实体来代替它。实际上,你可以在这里写任何文本。第二个参数告诉编译器应该把使用这个过时的程序实体当作一种错误。它的默认值是false,也就是说编译器对此会产生一个警告。

  当我们尝试编译上面这段程序的时候,我们将会得到一个错误: 
  AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'

  开发定制特性(custom attributes)

  现在让我们来看看如何开发我们自己的特性。 
  首先我们要从System.Attribute派生出我们自己的特性类(一个从System.Attribute抽象类继承而来的类,不管是直接还是间接继承,都会成为一个特性类。特性类的声明定义了一种可以被放置在声明之上新的特性)。

1 using System; 2 public class HelpAttribute : Attribute 3 { 4 }

  不管你是否相信,我们已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像上面我们使用Obsolete attribute一样。

  

1 [Help()]
2 public class AnyClass
3 {
4 }

  注意:对一个特性类名使用Attribute后缀是一个惯例。然而,当我们把特性添加到一个程序实体,是否包括 Attribute后缀是我们的自由。编译器会首先在System.Attribute的派生类中查找被添加的特性类。如果没有找到,那么编译器会添加 Attribute后缀继续查找。

到目前为止,这个特性还没有起到什么作用。下面我们来添加些东西给它使它更有用些。

 1 using System;
 2 public class HelpAttribute : Attribute
 3 {
 4     public HelpAttribute(String Descrition_in)
 5     {
 6         this.description = Description_in;
 7     }
 8     protected String description;
 9     public String Description
10     {
11         get
12         {
13             return this.description;
14         }
15     }
16 }
17 [Help("this is a do-nothing class")]
18 public class AnyClass
19 {
20 }

在上面的例子中,我们给HelpAttribute特性类添加了一个属性并且在后续的部分中我们会在运行时环境中查寻它。

  定义或控制特性的使用

  AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。 
  AttributeUsage有三个属性,我们可以把它放置在定制属性前面。第一个属性是:

  ValidOn 
  通过这个属性,我们能够定义定制特性应该在何种程序实体前放置。一个属性可以被放置的所有程序实体在AttributeTargets enumerator中列出。通过OR操作我们可以把若干个AttributeTargets值组合起来。

  AllowMultiple 
  这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次。

  Inherited 
  我们可以使用这个属性来控制定制特性的继承规则。它标记了我们的特性能否被继承。

  下面让我们来做一些实际的东西。我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。

 1 using System;
 2 [AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
 3 Inherited = false ]
 4 public class HelpAttribute : Attribute
 5 {
 6     public HelpAttribute(String Description_in)
 7     {
 8         this.description = Description_in;
 9     }
10     protected String description;
11     public String Description
12     {
13         get
14         {
15             return this.description;
16         }
17     }
18 }

  先让我们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:

  

1 [Help("this is a do-nothing class")]
2 public class AnyClass
3 {
4     [Help("this is a do-nothing method")] //error
5     public void AnyMethod()
6     {
7     }
8 }

  编译器报告错误如下:
  AnyClass.cs: Attribute 'Help' is not valid on this declaration type. 
  It is valid on 'class' declarations only.

  我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:

  Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,Parameter,Delegate

All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate

  ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface

  下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。

1 [Help("this is a do-nothing class")]
2 [Help("it contains a do-nothing method")]
3 public class AnyClass
4 {
5     [Help("this is a do-nothing method")] //error
6     public void AnyMethod()
7     {
8     }
9 }

  它产生了一个编译期错误。 
  AnyClass.cs: Duplicate 'Help' attribute

  Ok,现在我们来讨论一下最后的这个属性。Inherited, 表明当特性被放置在一个基类上时,它能否被派生类所继承。

1 [Help("BaseClass")]
2 public class Base
3 {
4 }
5 public class Derive : Base
6 {
7 }

  这里会有四种可能的组合:

1 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
2 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
3 [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
4 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ] 

  第一种情况:

  如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false。

  第二种情况:

  和第一种情况相同,因为inherited也被设置为false。

  第三种情况:

  为了解释第三种和第四种情况,我们先来给派生类添加点代码:

1 [Help("BaseClass")]
2 public class Base
3 {
4 }
5 [Help("DeriveClass")]
6 public class Derive : Base
7 {
8 }

  现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。

  第四种情况:

  在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true。

定义或控制特性的使用AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如何被使用。

属性和特性的区别可以参考一下: http://developer.51cto.com/art/200908/147097.htm

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Foxalien/archive/2009/12/05/4946672.aspx

WPF 可触摸移动的ScrollViewer控件

 

ListBox支持触摸滑动,而ScrollViewer默认不支持。

ScrollViewer如需要添加上下/左右触摸移动,需要在Touch事件中处理。

处理如下:封装成一个用户控件

  1. TouchDown事件中记录起始点,并添加对TouchMove事件的监听
  2. TouchUp事件中注销TouchMove事件的监听
  3. 在TouchMove事件中,处理移动的偏移量。起始位置减去偏移量,即为当前滚动条的位置。

注:ScrollViewer滚动到指定位置(指定位置=起始位置-移动的偏移量,滚动方向和手势方向相反)

 1     /// <summary>
 2     /// 可触摸滚动的ScrollViewer控件
 3     /// </summary>
 4     public class TouchableScrollViewer : ScrollViewer
 5     {
 6         //触摸点的坐标
 7         Point _startPosition;
 8         //滚动条当前位置
 9         double _startVerticalOffset;
10         double _startHorizontalOffset;
11         public TouchableScrollViewer()
12         {
13             TouchDown += TouchableScrollViewer_TouchDown;
14
15             TouchUp += TouchableScrollViewer_TouchUp;
16         }
17         private void TouchableScrollViewer_TouchDown(object sender, TouchEventArgs e)
18         {
19             //添加触摸移动监听
20             TouchMove -= TouchableScrollViewer_TouchMove;
21             TouchMove += TouchableScrollViewer_TouchMove;
22
23             //获取ScrollViewer滚动条当前位置
24             _startVerticalOffset = VerticalOffset;
25             _startHorizontalOffset = HorizontalOffset;
26
27             //获取相对于ScrollViewer的触摸点位置
28             TouchPoint point = e.GetTouchPoint(this);
29             _startPosition = point.Position;
30         }
31
32         private void TouchableScrollViewer_TouchUp(object sender, TouchEventArgs e)
33         {
34             //注销触摸移动监听
35             TouchMove -= TouchableScrollViewer_TouchMove;
36         }
37
38         private void TouchableScrollViewer_TouchMove(object sender, TouchEventArgs e)
39         {
40             //获取相对于ScrollViewer的触摸点位置
41             TouchPoint endPoint = e.GetTouchPoint(this);
42             //计算相对位置
43             double diffOffsetY = endPoint.Position.Y - _startPosition.Y;
44             double diffOffsetX = endPoint.Position.X - _startPosition.X;
45
46             //ScrollViewer滚动到指定位置(指定位置=起始位置-移动的偏移量,滚动方向和手势方向相反)
47             ScrollToVerticalOffset(_startVerticalOffset - diffOffsetY);
48             ScrollToHorizontalOffset(_startHorizontalOffset - diffOffsetX);
49         }
50     }

Demo下载

提升能力,才是王道
 

.NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用

 

.NET程序员一定最熟悉所见即所得式开发,熟悉的Visual Studio开发界面,熟悉的C#代码。

Smobiler也是因为具备这样的特性,使开发人员,可以在VisualStudio上,像开发WinForm一样拖拉控件,让许多人在开发APP时,再次回到所见即所得的开发方式中去。

Smobiler的快速开发,让Amanda看到了程序员们分享的各式各样的应用。

来自程序员的分享

Git使用总结 Asp.net生命周期与Http协议 托管代码与非托管代码的区别 通过IEnumerable接口遍历数据 依赖注入与控制反转 C#多线程——优先级 AutoFac容器初步 C#特性详解 C#特性详解 WPF 可触摸移动的ScrollViewer控件 .NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用的更多相关文章

  1. WPF 可触摸移动的ScrollViewer控件

    ListBox支持触摸滑动,而ScrollViewer默认不支持.需要设置PanningMode属性,如果不设置PanningMode,如何自定义触摸滑动? ScrollViewer如需要添加上下/左 ...

  2. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  3. Asp.net生命周期与Http协议

    Http协议,底层的东西还是不是特别熟悉,感觉要经过沉淀之后才能理解这些东西吧 1.Asp.net生命周期 Asp.net生命周期: 从发起请求开始,到IIS进行处理的全部过程,然后再到获取结果 当请 ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入:控制反转

    ASP.NET Core框架建立在一些核心的基础框架之上,这些基础框架包括依赖注入.文件系统.配置选项和诊断日志等.这些框架不仅仅是支撑ASP.NET Core框架的基础,我们在进行应用开发的时候同样 ...

  5. ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下

    先简单了解一这个几个 名词的意思. 控制反转(IOC) 依赖注入(DI) 并不是某种技术. 而是一种思想.一种面向对象编程法则 什么是控制反转(IOC)?  什么是依赖注入(DI) 可以点击下面链接 ...

  6. ASP.NET中IOC容器Autofac(依赖注入DI 控制反转IOC)

    IOC的一个重点是在程序运行中,动态的向某个对象提供它所需要的其他对象.这一点是通过DI来实现的.Autofac则是比较流行的一款IOC容器. IoC和DI有什么关系呢?其实它们是同一个概念的不同角度 ...

  7. ASP.NET生命周期详解

    最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...

  8. ASP.NET生命周期详解 [转]

    最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等 ...

  9. ASP.NET生命周期详解(转)

    看到好文章需要分享. 最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多 ...

随机推荐

  1. Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  2. 第一个程序-Hello world

    创建HelloWorld项目 1.在Android Studio的欢迎界面点击Start a new Android Studio project 2.填写Application name(表示应用名 ...

  3. jQuery插件示例笔记

    插件的种类 封装对象方法的插件 将对象方法封装起来,用于对通过选择器获取的jQuery对象进行操作. //注意,为了更好的兼容性开始前有个分号 ;(function($){ //此处将$作为匿名函数的 ...

  4. iOS 捕获程序崩溃日志

    iOS开发中遇到程序崩溃是很正常的事情,如何在程序崩溃时捕获到异常信息并通知开发者? 下面就介绍如何在iOS中实现: 1. 在程序启动时加上一个异常捕获监听,用来处理程序崩溃时的回调动作 NSSetU ...

  5. 简单总结es6箭头符号

    1.es6箭头符号的几种写法 (1)没有参数 ()=>1*1 (2)一个参数 x=>x*x (3)两个参数以及多个参数 (x,y,z)=>x*y*z 2.箭头符号不会绑定this.a ...

  6. linux CMakeLists.txt 语法

    CMake入门教程 参考文献:http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/index.html 官方网址:http://www.cmak ...

  7. 如何查看Oracle日志

    Oracle日志查看 一.Oracle日志的路径: 登录:sqlplus "/as sysdba" 查看路径:SQL> select * from v$logfile; SQ ...

  8. saltstack之crontab管理用法

    一.创建定时任务 crontab: #脚本脚识 cron.present: #模板:cron 计划任务 功能:present - name: /usr/sbin/ntpdate times.aliyu ...

  9. Shadow Map 原理和改进 【转】

    http://blog.csdn.net/ronintao/article/details/51649664 参考 1.Common Techniques to Improve Shadow Dept ...

  10. [GLSL]着色器周记02——火焰特效 【转】

    http://www.cnblogs.com/tkgamegroup/p/4214081.html 这周学了好多.包括伪随机数.柏林噪声.先说伪随机数.伪随机数我们用的是周期函数而不是那种由前一项乘一 ...