0%

选项 参数 目标 描述
/MT - 代码生成 多线程(非CLR)
/MTd - 代码生成 多线程调试(非CLR)
/MD - 代码生成 多线程DLL
/MDd - 代码生成 多线程调试DLL
/Yu 预编译头 是否使用预编译头
/clr - 公共语言运行时
/D 预处理器定义
/Od - 禁用优化
/O1 - 最大优化(优选大小)
/O2 - 最大优化(优选速度)
/Ox - 优化(优选速度)
/ZI - 编辑并继续

工具准备

  1. gdal源码
  2. proj4源码
  3. geos源码
  4. hdf4源码
  5. hdf5源码

步骤

一、使用VS2019编译proj4 C++源码

  1. 按图示选择源码路径与将要生成的vs解决方案的存放路径。

    images

  2. 点击Configure并按图所示在弹出的窗口中选择Visual Studio版本。

    images

  3. 确定后日志信息最后一行出现Configuring Done即表示配置检测成功,顺便修改一下 CMAKE_INSTALL_PREFIX变量,此变量是生成的解决方案对应的INSTALL工程的安装目录,点击Generate生成。

    images

  4. 出现Generating Done字样即表示生成VS解决方案成功。

    images

  5. 点击OpenProject会自动使用Visual Studio 打开刚生成的解决方案。选择Release配置项,并生成INSTALL工程,即可将PROJ4的编译结果安装到之前配置的 CMAKE_INSTALL_PREFIX 变量的路径下。

    images

  6. 生成结果如下所示。

    images

二、编译geos C++源码

  1. 编译方式与Proj4一致,如下图所示。

    images
    images
    images
    images
    images
    images

三、编译hdf4 C++源码

  1. 编译方式与之前一直,不同之处在于参数检测时的配置,如下图所示

    images

  2. 打开解决方案后改为Release配置并生成INSTALL项目会报如下所示错误。

    images

  3. 由于源码提供的Cmake文件有问题,所以之前没有选择zlib,与jpeg 的支持,待生成解决方案后,自行配置,配置方式如下所示。

  4. 如下图为hdf4-shared与hdf4-static两项目配置附加目录

    images

  5. 如下图为hdf4-shared配置附加依赖项

    images

  6. 再次生成INSTALL项目,如果没有hdf-shared 与 hdf-static的错误 即为成功,其它的测试项目的错误不予理会。生成结果如下所示。

    images

四、编译hdf5 C++源码

  1. 同proj

五、编译gdal C++源码

  1. 修改nmake.opt配置文件

    GDAL_HOME = “D:\gdal\release\gdal”

    PROJ_INCLUDE = -Id:\gdal\release\proj\local\include
    PROJ_LIBRARY = d:\gdal\release\proj\local\lib\proj_4_9.lib

    GEOS_DIR=d:/gdal/release/geos
    GEOS_CFLAGS = -I$(GEOS_DIR)/include -DHAVE_GEOS
    GEOS_LIB = $(GEOS_DIR)/lib/libgeos.lib

    HDF4_PLUGIN = YES
    HDF4_DIR = D:\gdal\release\hdf4
    HDF4_LIB = /LIBPATH:$(HDF4_DIR)\lib libhdf.lib
    HDF4_INCLUDE = $(HDF4_DIR)\include

    HDF5_PLUGIN = YES
    HDF5_DIR = D:\GDAL\release\hdf5
    HDF5_LIB = $(HDF5_DIR)\lib\libhdf5.lib

  2. 打开 x64 Native Tools Command Prompt for VS 2019, 并改变路径到GDAL的源码路径下执行 nmake -f makefile.vc MSVC_VER=1900 WIN64=1 INSTALL,会报以下错误

    images

  3. 通过修改源码临时解决。

    images

  4. 重新执行命令

    images

六、配置环境变量

Path加入以下变量
./gdal/bin
./geos/bin
./hdf4/bin
./hdf5/bin
./jpeg/bin
./proj/bin
./proj/share
./szip/bin
./zlib/bin
加入环境变量GDAL_DATA
./gdal/data

七、使用Swig生成C#的平台调用代码

  1. 打开swig/csharp文件加如下所示

    images
    images

  2. 打开 x64 Native Tools Command Prompt for VS 2019, 并改变路径到GDAL的源码路径下执行 nmake /f makefile.vc interface

    images

  3. 目录结果如下所示,其中const、gdal、ogr、osr路径下将生成csharp可以调用的源码。

    images
    images
    images
    images

  4. 再次执行命令,nmake /f makefile.vc 路径保持不变,结果如下所示

    images

工具准备

  1. gdal源码
  2. proj6源码

步骤

一、使用VS2019编译sqlite-3 C++源码

  1. 进入下载sqlite官方网站[https://www.sqlite.org/download.html]下载如图所示两个文件包,本次下载的是64位版本,也可按需下载32位版本。下载完成后解压到本地并包含如图所示4个文件。

    sqlite
    sqlite

  2. 启动VS2019在配置页面新建工程项目,选择 [C++ 空项目] 模板,设置好项目名称后并创建,然后将sqlite3.h和sqlite3ext.h两个文件按图所示加入到项目工程中的头文件中,将sqlite3.c和sqlite3.def两个文件加入到源文件中。

    sqlite
    sqlite
    sqlite

  3. 打开项目属性对话框 ,选择Release配置,平台选择x64,然后在左侧选项卡中按顺序展开 C/C++ -> 预处理器,在预处理器定义处删除原有定义内容,并输入以下内容。

    _USRDLL
    SQLITE_ENABLE_RTREE
    SQLITE_ENABLE_COLUMN_METADATA
    SQLITE_ENABLE_FTS5
    SQLITE_ENABLE_UNLOCK_NOTIFY

    预处理器定义

  4. 在项目属性对话框左侧展开[链接器 -> 输入],右侧模块定义文件处输入"sqlite3.def"

    模块定义文件

  5. 在项目属性对话框左侧展开[配置属性][常规],右侧配置类型选择静态库(ilb).

    修改配置类型

  6. 打开模块定义文件sqlite3.def,并拉到最后一行,并追加 “sqlite3_unlock_notify” 内容

    模块定义文件

  7. 一切配置完成后,使用Release64生成项目,即可在输出目录中看到输出成果

    sqlite

二、使用CMake编译Proj6

  1. 解压PROJ

    proj

三、编译GDAL

  1. 解压GDAL

    gdal

  2. 生成VS项目工程文件(此步骤弃用)

    generate_vcproj

  3. 修改nmake.opt 文件

    搜索并修改项

LiveChart图表类

CartesianChart柱状图Label较多时倾斜显示,使用LabelsRotation属性,并将Separator.Step设置为1.

1
2
3
4
5
6
7
8
9
10
11
12
<lvc:CartesianChart x:Name="chart" Series="{Binding SeriesCollection}" LegendLocation="Right">
<lvc:CartesianChart.AxisX>
<lvc:Axis Title="{Binding AxisXName}" LabelsRotation="45" Labels="{Binding Labels}" FontWeight="ExtraLight" FontSize="16" MaxRange="1" >
<lvc:Axis.Separator>
<lvc:Separator Step="1"></lvc:Separator>
</lvc:Axis.Separator>
</lvc:Axis>
</lvc:CartesianChart.AxisX>
<lvc:CartesianChart.AxisY>
<lvc:Axis Title="{Binding AxisYName}" LabelFormatter="{Binding Formatter}" FontWeight="ExtraLight" FontSize="12"></lvc:Axis>
</lvc:CartesianChart.AxisY>
</lvc:CartesianChart>

ViewModel中通过附加属性的改变回调可以获得依赖对象控件

通过后代DataContext中的属性绑定到控件的附加属性上触发附加属性回调以获得控件。

数据上下文类

1
2
3
4
5
6
7
8
9
10
11
12
public class DataContext:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _text;
public string Text{
get{return _text;}
set{
_text = value;
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("Text"));
}
}
}

依赖属性类(可置于任何地方)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
namespace MyProperty
{
public static class MessageInfo
{
//定义依赖属性
public static readonly DependencyProperty MessageInfoProperty =
DependencyProperty.RegisterAttached(
"MessageInfo",
typeof(string),
typeof(MessageInfo),
new PropertyMetadata(new PropertyChangedCallback(MessageInfoChanged)));
//回调中操控依赖对象控件
private static void MessageInfoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var box = d as System.Windows.Controls.TextBox;
if (null != box)
{
box.Text = e.NewValue as string;
box.ScrollToEnd();
}
}
//实际运行时不会进入此方法体,但编译时会以此来检查依赖属性存在与否
public static void SetMessageInfo(System.Windows.Controls.TextBox target, string value)
{
//target.SetValue(MessageInfoProperty, value);
}
}
}

前台XAML代码

绑定的text 常规绑定

1
2
3
xmlns:xc="MyProperty"

<TextBox xc:MessageInfo.MessageInfo="{Binding Text}"/>

依赖属性与附加属性

  • CLR属性

    类的方法在内存中只有一个拷贝,无论是否为静态方法,所以CLR属性保证了安全性,又不会增加内存的负担。

  • 依赖属性

    依赖属性自己没有值,通过Binding从数据源获取值

  • 依赖对象

    拥有依赖属性的对象

下面手动实现一个依赖对象,并包含一个依赖属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Student:DependencyObject
{
//依赖属性
public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name",typeof(string),typeof(Student));
//CLR属性包装器
public string Name{
get{
return (string)GetValue(NameProperty);
}
set{
SetValue(NameProperty,value)
}
}
//SetBinding包装
public BindingExpressionBase SetBinding(DependencyProperty dp,BindingBase binding){
return BindingOperations.SetBinding(this,dp,binding);
}
}

依赖属性的优势

  • 依赖属性加入了属性变化通知、限制、验证等功能。这样可以使我们更方便地实现应用,同时大大减少了代码量。许多之前需要写很多代码才能实现的功能,在WPF中可以轻松实现。
  • 节约内存:在WinForm中,每个UI控件的属性都赋予了初始值,这样每个相同的控件在内存中都会保存一份初始值。而WPF依赖属性很好地解决了这个问题,它内部实现使用哈希表存储机制,对多个相同控件的相同属性的值都只保存一份。

资源

定义位置

应用程序级

在App.xaml中定义

1
2
3
4
5
6
7
8
<Application x:Class="WPFResource.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<SolidColorBrush Color="Gold" x:Key="myGoldBrush" />
</Application.Resources>
</Application>

在ApplicationResourceDemo.xaml中使用

1

资源字典

概述

构成

  1. entry:定义整个编译过程的起点
  2. output:定义整个编译过程的终点
  3. module:定义模块module的处理方式
  4. plugin:对编译完成后的内容进行二次加工
  5. resolve.alias:定义模块的别名

安装

先全局安装webpack和webpack-cli

1
npm install webpack webpack-cli -g
1
2
3
4
mkdir webpacktest
cd webpacktest
npm init
npm install webpack webpack-cli -D

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module.exports = {
entry:'./index.js',
output:{
path:path.resolve(process.cwd(),'dist/'),
filename:'[name].js'
},
resolve:{
alias:{jquery:'src/lib/jquery.js'}
},
plugins:[
new WebpackNotifierPlugin()
],
module:{
loaders:[{
test:/\.js[x]?$/,
exclude:/node_modules/,
loader:'babel-loader'
},{
test:/\.less$/,
loaders:['style-loader','css-loader','less-loader']
},{
test:/\.html$/,
loader:'html-loader?'+JSON.stringify({minimize:false})
}]
}
}

NuGet

NuGet是开放源代码包管理系统,可以简化将库合并到项目解决方案的过程。

SDK(软件开发工具包)

SDK是文件集合,Visual Studio 将其视为单个引用项。

EntityFramework

创建对象关系映射上下文(ORM Context)

上下文类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class EventsMenusContext:DbContext
{
public EventsMenusContext(DbContextOptions options):base(options) { }
public DbSet<Menu> Menus { get; set; }
public DbSet<Event> Events { get; set; }
}
//如果项目中含有多个上下文类,为避免报错写成下面这样
public class EventsMenusContext:DbContext
{
public EventsMenusContext(DbContextOptions<EventsMenusContext> options):base(options) { }
public DbSet<Menu> Menus { get; set; }
public DbSet<Event> Events { get; set; }
}

通过自定义连接创建上下文

1
2
3
DbContextOptionsBuilder builder = new DbContextOptionsBuilder();
builder.UseSqlServer(Configuration["Data:ConnectionStrings:MyConnection"]);
EventsContext context = new EventsContext(builder.Options);

依赖注入到控制器

1
services.AddScoped<context>();

简洁写法

1
2
3
4
5
6
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServer()
.AddDbContext<EventsMenusContext>(options=>
options.UseSqlServer(Configuration["Data:ConnectionStrings:MyConnection"]));
}

如果使用自动生成控制器功能,需要在上下文类中加入无参构造函数并重写上下文类中的方法,控制器及视图创建完成后,在使用注入方法时删除构造函数和重写方法。

1
2
3
4
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=mydb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
}

ASP.NET CORE VUE.JS IVIEW

  1. Nuget RequireJS
  2. Nuget require.css
  3. Nuget Vue.Js.IView.UI

Ocelot

介绍

Ocelot是一个用.NETCore实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing集成。

HTMLHelper

HTML 帮助器用于修改 HTML 输出。

HTML 帮助器

通过 MVC,HTML 帮助器类似于传统的 ASP.NET Web Form 控件。
类似 ASP.NET 中的 web form 控件,HTML 帮助器用于修改 HTML。但是 HTML 帮助器更轻。与 web form 控件不同,HTML 帮助器没有事件模型和 view state。
在大多数情况下,HTML 帮助器仅仅是返回字符串的方法。
通过 MVC,您能够创建自己的帮助器,或者使用内建的 HTML 帮助器。

标准的 HTML 帮助器

MVC 包含了大多数常用的 HTML 元素类型的标准帮助器,比如 HTML 链接和 HTML 表单元素。

HTML 链接

呈现 HTML 链接的最简单方法是使用 HTML.ActionLink() 帮助器。
通过 MVC,Html.ActionLink() 不连接到视图。它创建控制器操作(controller action)的连接。

Razor 语法:

1
@Html.ActionLink("About this Website", "About")

ASP 语法:

1
<%=Html.ActionLink("About this Website", "About")%>

第一个参数是链接文本,第二个参数是控制器操作的名称。
上面的 Html.ActionLink() 帮助器,输出以下 HTML:

1
<a href="/Home/About">About this Website</a>

Html.ActionLink() 帮助器的若干参数:

参数 描述
linkText 定位点元素的内部文本。
actionName 操作的名称。
controllerName 控制器的名称。
protocol URL 协议,如“http”或“https”。
hostname URL 的主机名。
fragment URL 片段名称(定位点名称)。
routeValues 一个包含路由参数的对象。
htmlAttributes 一个对象,包含要为该元素设置的 HTML 特性。
注释:您可以向控制器操作传递值。例如,您能够像数据库编辑操作传递数据库记录的 id。
Razor 语法 C#:
1
@Html.ActionLink("Edit Record", "Edit", new {Id=3})

Razor 语法 VB:

1
@Html.ActionLink("Edit Record", "Edit", New With{.Id=3})

上面的 Html.ActionLink() 帮助器,输出以下 HTML:

1
<a href="/Home/Edit/3">Edit Record</a>

HTML 表单元素

以下 HTML 帮助器可用于呈现(修改和输出)HTML 表单元素:

  • BeginForm()
  • EndForm()
  • TextArea()
  • TextBox()
  • CheckBox()
  • RadioButton()
  • ListBox()
  • DropDownList()
  • Hidden()
  • Password()
    ASP.NET 语法 C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and 
try again.") %>
<% using (Html.BeginForm()){%>
<p>
<label for="FirstName">First Name:</label>
<%= Html.TextBox("FirstName") %>
<%= Html.ValidationMessage("FirstName", "*") %>
</p>
<p>
<label for="LastName">Last Name:</label>
<%= Html.TextBox("LastName") %>
<%= Html.ValidationMessage("LastName", "*") %>
</p>
<p>
<label for="Password">Password:</label>
<%= Html.Password("Password") %>
<%= Html.ValidationMessage("Password", "*") %>
</p>
<p>
<label for="Password">Confirm Password:</label>
<%= Html.Password("ConfirmPassword") %>
<%= Html.ValidationMessage("ConfirmPassword", "*") %>
</p>
<p>
<label for="Profile">Profile:</label>
<%= Html.TextArea("Profile", new {cols=60, rows=10})%>
</p>
<p>
<%= Html.CheckBox("ReceiveNewsletter") %>
<label for="ReceiveNewsletter" style="display:inline">Receive Newsletter?</label>
</p>
<p>
<input type="submit" value="Register" />
</p>
<%}%>

Consul

  1. 下载Consul服务程序
  2. 运行
1
consul.exe agent -dev
  1. 监控页面
1
127.0.0.1:8500/

Highlight语法高亮

地址 https://github.com/highlightjs/highlight.js/tree/master/src/styles
https://highlightjs.org/download/

获取服务端与客户端地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public IActionResult Index()
{
//获取客户端的IP地址
string clientIpAddress = httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
this.ViewData["ClientIpAddress"] = clientIpAddress;

//获取服务器上所有网卡的IP地址
NetworkInterface[] networks = NetworkInterface.GetAllNetworkInterfaces();
string serverIpAddresses = string.Empty;

foreach (var network in networks)
{
var ipAddress = network.GetIPProperties().UnicastAddresses.Where(p => p.Address.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(p.Address)).FirstOrDefault()?.Address.ToString();

serverIpAddresses += network.Name + ":" + ipAddress + "|";
}

this.ViewData["ServerIpAddresses"] = serverIpAddresses;

return View();
}

概述

Consul是一个分布式、高可用的扩展的用于服务发现和配置的工具

特性

  • 服务发现
    使用Consul可以更加简单的通过DNS或者HTTP方式来进行服务的注册和发现,外部的服务也可以进行注册。
  • 健康检查
    使用Consul的健康检查可以确认集中服务的状态信息,这项功能的集成有助于更好地进行路由分发等操作。
  • Key/Value存储
    可以通过简单的HTTP API进行Key/Value的使用,使得动态配置、特性标记、Leader选举等变得更加灵活。
  • 多数据中心
    Consul内建支持多数据中心,可以不需要复杂的配置就可以实现任意数量区域的支持。
  • 服务网格
    应用可以在服务网格配置使用sidecar代理来建立TLS连接,而在使用中也可以做到对于连接的透明性和无意识。

概念

  • Consul的官网组织图如下所示

    images

  • CLIENT
    CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。
  • SERVER
    SERVER表示consul的server模式,表明consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化到本地,这样遇到故障,信息是可以被保留的。
  • SERVER-LEADER
    是SERVER的老大,与SERVER不一样的是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康检查。

安装

Docker中安装

  1. 拉取镜像

    1
    docker pull consul
  2. 宿主机创建文件夹

    期望容器中的配置文件、数据、日志再容器异常关闭或主动删除后保留,则需要配置挂载

    1
    mkdir -p /data/consul/{conf,data}
  3. 启动启动 将Consul默认的8500端口映射到宿主机的8599端口

    1
    docker run --name consul -p 8500:8500 -v /data/consul/conf/:/consul/conf/ -v /data/consul/data/:/consul/data/ -d consul

Windows下的测试安装

  1. 下载consul.exe文件

  2. 启动

    1
    consul.exe agent --dev
  3. 浏览器打开127.0.0.1:8500,如下所示即为成功

    consul

Consul的服务注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using Consul;

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
ConsulClient client = new ConsulClient(config => {
config.Address = new Uri(Configuration["ConsulServer:Uri"]);
config.Datacenter = Configuration["ConsulServer:Datacenter"];
});
Task<WriteResult> result = client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = "BlogService_" + Guid.NewGuid().ToString().Substring(0, 7),//服务编号,不能重复,用Guid最简单
Name = "BlogService",//服务的名字
Address = ipAddress,//我的ip地址(可以被其他应用访问的地址,本地测试可以用127.0.0.1,机房环境中一定要写自己的内网ip地址)
Port = port,//我的端口
Check = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务停止多久后反注册
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔
HTTP = $"http://{ipAddress}:{port}/blog/health",//健康检查地址,
Timeout = TimeSpan.FromSeconds(5)
}
});
}