Dotnet专业组件开发揭密(二)

Dotnet专业组件开发揭密(三) Dotnet专业组件开发揭密(三)--TypeDescriptor内部机制及其应用(中) 本文代码下载官方地地://Code/Csharp/BlogCode/TypeDescriptionProviderDemo.rar优快云地址:http://download.youkuaiyun.com/user/BlueDog     上一篇我们讲到了如何利用ICustomTypeDesc 阅读详情

Dotnet专业组件开发揭密(二)

--TypeDescriptor内部机制及其应用(上)

 

本文代码下载

官方地址://Code/Csharp/BlogCode/TypeDescriptorDemo.rar

优快云地址:http://download.youkuaiyun.com/user/BlueDog

 

本篇要讲述的是System.ComponentModel空间里最神奇的类,也是最重要的类,几乎所有的高级控件设计人员都必需掌握的类—TypeDescriptor。它的作用类似于反射,但是它是可以动态更改类信息的!虽然我们可能很少碰到直接使用它的情况,但是它的原理必须理解,这样你才不会对VS中一些机制产生疑问。

我们知道元数据可以说是Dotnet的基础,一旦编译后,就不能更改,而我们经常使用System.Reflection命名空间里的一些类来查看这些元数据,但是我们并没有办法去更改这些元数据。但是往往在设计阶段我们有这个需要,比如我们对某个控件要求在设计时确定一个属性的初使值,但是这个属性在运行时是不充许改变的,或者根本就不能公开,有没有什么好办法呢?再问你一个问题,以前的ActiveX组件在导入Dotnet环境后,你想过没有,原来的ActiveX控件是没有所谓的元数据的,哪为什么我们可以通过“属性窗口”来查看它的属性呢?答案还是TypeDescriptor起了作用。

说起TypeDescriptor,就不能不说到它最主要的“客户”—PropertyGrid,这个强大的微软居然遮遮掩掩不愿意直接公开的控件(呵呵,是不是很长的定语呀),以及一个非常有用的接口ICustomTypeDescriptor。嗯,我们先来说说PropertyGrid,从其名字就可以知道它可以显示一个类实例的属性,我们知道它只能显示一个类的属性(Property),但并不能显示公共字段。我们将在后面介绍如何实现让它显示公共字段。ICustomTypeDescriptor,则是为对象提供动态自定义类型信息的接口。不要小看了这句话,神奇的功能都是它实现的。

它们三者的关系是这样子的,当用PropertyGrid来查看一个类的属性信息时,它并不是我们一般认为的会通过Reflection空间里的类来进行反射,找到元数据,然后显示出来。实际上它利用TypeDescriptor来查看类实例的属性信息。而TypeDescriptor它的内部有几个逻辑判断,看看A)这个类是不是实现了ICustomTypeDescriptor接口,如果是它会用这个接口来返回属性信息,如果没有它会用默认的反射来返回;B)它会查看同一个逻辑容器里是不是有实现了IextenderProvider接口的类,如果有它会进行特殊处理;C)如果需要过滤一些属性,它会过滤掉。正因为它内部有如此复杂的机制,那么我们便可以通过第一步或第二步来影响返回的属性信息。实际上这里大家就知道了我们上一篇文章里为什么扩展机制如何起作用了。当然TypeDescriptor远不止我们上面所简述的这么简单,我们会在后面的篇章里深入探索它。

现在我们来回答关于ActiveX控件属性的问题。实际上,当我们拖入一个ActiveX组件时,VS会为我们产生一个包装类,它继承于System.Windows.Forms.AxHost这个纯虚的类,而这个类正好实现了ICustomTypeDescriptor,因此“属性窗口”通过TypeDescriptor来查看这个ActiveX组件时,它发现它实现了ICustomTypeDescriptor接口,因此它为用这个接口来取得组件的属性信息。从而实现了可以取得ActiveX组件的属性信息。下面的图就是ActiveX控件TreeView在VS环境下显示的属性情况。

   我们现在来完成前面所说的如何在PropertyGrid里显示公共字段,因为我们将在以后的揭密里再对它进行更有趣的应用。

我们来看一个简单的职员类

public class Employee

      {

          public string Name;

          public bool Sex;

          public DateTime Born;

}

另外还有一个用属性实现的类EmployeeByProperty以及一个用ICustomTypeDescriptor接口实现的类EmployeeByICustomTypeDescriptor,它实际是继承于FieldToPropertyTypeDescriptor这个虚继类,由它来实现接口。另外还提供了一个可以动态包装Employee,可以使它同样达到EmployeeByICustomTypeDescriptor的包装代理类FieldToPropertyProxyTypeDescriptor,两个黑体显示的类,稍作一些修改,可以相当的有用。当然还有一个类FieldPropertyDescriptor也是必需要有的,它继承于PropertyDescriptor,用于描述具体的某个属性信息。

需要稍作说明的是FieldToPropertyTypeDescriptor这个类,当TypeDescriptor利用它返回属性集合时,首先它会用TypeDescriptor.GetProperties取得默认的元数据,然后再将每个字段信息转换成FieldPropertyDescriptor,然后加入属性集合里。下面便是这一小段代码的核心:

props = new PropertyDescriptorCollection(null);

foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this, attributes, true))

{

      props.Add(prop);

}

foreach (FieldInfo field in GetType().GetFields())

{

FieldPropertyDescriptor fieldDesc = new FieldPropertyDescriptor(field);

if (!filtering || fieldDesc.Attributes.Contains(attributes)) props.Add(fieldDesc);

}

好了,其它还有疑问的地方我们可以通过MSDN进行查找。不过顺便说一句,这种做法并不是在2.0里的推荐做法,我们会在下一篇看到2.0里的做法。

 

参考资料:MSDN Magazine关于ICustomTypeDescriptor的文章(http://msdn.microsoft.com/msdnmag/issues/05/04/NETMatters/),有兴趣大家可以看一看。

 
Dotnet专业组件开发揭密(四) Dotnet专业组件开发揭密(四)--TypeDescriptor内部机制及其应用(下) 前两篇文章里我们TypeDescriptor是用来返回一个类的属性或事件描述符的,VS中使用的PropertyGrid就是通过它来取得一个类的属性的。而不是我们以为的是通过反射来做的。那么它的内部机制是如何的?TypeDescriptor它会进行几个判别,一是查看类是否实现了ICustomTy 阅读详情

相关推荐

30、数据绑定接口深度解析

本文深入解析了数据绑定中的关键接口,包括ICustomTypeDescriptor、ISupportInitialize、ISupportInitializeNotification、ICurrencyManagerProvider以及IList、IEnumerable、IBindingList和INotifyPropertyChanged等,从使用者与实现者的双重视角分析其作用与实现方式,并通过流程图直观展示数据绑定过程。旨在帮助开发者全面理解这些接口的工作机制,提升数据绑定的开发效率与应用性能。

garlic的博客 48

C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)

【转 http://blog.youkuaiyun.com/ronotian/article/details/3183907】 既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞定,让PropertyGrid显示Control的所有属性。可是这里显...

weixin_30405421的博客 1375

c# propertyGrid 属性显示为中文,支持下拉菜单选择文本

源代码,含例程。 加上代码中特性,就可以显示成中文,支持下拉菜单选择文本

Dotnet专业组件开发揭密(二)(转载)

转自http://www.cnblogs.com/mywebname/archive/2007/11/15/959732.html 本篇要讲述的是System.ComponentModel空间里最神奇的类,也是最重要的类,几乎所有的高级控件设计人员都必需掌握的类—TypeDescriptor。它的作用类似于反射,但是它是可以动态更改类信息的!虽然我们可能很少碰到直接使用它的情况,但是它的原理必须...

weixin_34174422的博客 126

PropertyGrid中的枚举显示为中文

两种方法实现PropertyGrid中的枚举显示为中文,在枚举项中若定义了Description,则显示Description,没有定义直接显示枚举name。代码可以直接使用。

LightGBM处理类别特征和缺失值有多省心?一个真实业务数据案例带你上手

本文通过真实电商数据案例,详细解析了LightGBM如何高效处理类别特征和缺失值。相比传统方法,LightGBM仅需一行代码即可自动处理高基数类别特征和缺失值,大幅提升模型训练效率和预测准确度,特别适合业务场景中的脏数据处理。

weixin_30689307的博客 460

Dotnet专业组件开发揭密(一)

Dotnet专业组件开发揭密(一) --扩展功能提供程序本文代码下载官方地址://Code/Csharp/BlogCode/ExtenderProvider.rar优快云地址:http://download.youkuaiyun.com/source/231264 很多人会以为写组件是件容易的事,也许某些方面是这样的,比如你可以很简单地实现一个自定义的功能。但是写出来的组件好象跟

BlueDog专栏 2555

基于Autoware制作高精地图(一)

基于Autoware制作高精地图(一) ​开始进入正题,也是最近在忙的一件事,制作高精地图。 高精地图的制作大概分为以下四个流程(不一定完全正确): 1.构建点云地图; 2.点云地图标注; 3.制作OpenDrive地图; 4.地图存储索引。 这篇文章主要讲解如何构建点云地图。 首先我们要有一段自己录制的激光雷达点云数据,这里推荐大家采用Velodyne16线激光雷达,因为这里我们构建的点云底图是三维的,而采用Velodyne而不是速腾聚创(rslidar)等其他品牌的原因是Autoware里面有一个选项是

weixin_44570248的博客 7797

Dotnet专业组件开发揭密

很多人会以为写组件是件容易的事,也许某些方面是这样的,比如你可以很简单地实现一个自定义的功能。但是写出来的组件好象跟专业厂家开发的组件程序是不是有些差距呢?那么如何写一个专业组件呢,写专业组件要掌握哪些知识呢,它们的内部机理是什么呢?如果你对此感兴趣的话,那么这个系列实在是很值得你来看一看的。本篇是要介绍如何扩展一个已有的组件功能。比如用户提出来要在TextBox控件上实现一个取得焦点后实

EricChina的专栏 1260

景观格局指数计算方法及代表的生态学意义(待补充)

景观指数 斑块密度(PD) 斑块密度(PD)表现某种斑块在景观中的密度,可反映出景观整体的异质性与破碎度[17],公式为PD=NP/A(1)式中NP———斑块数量,个A———景观或斑块的总面积,hm2PD———斑块密度,个/hm2 最大斑块指数(LPI) 最大斑块指数(LPI)用于确定景观中的优势斑块类型,间接反映人类活动干扰的方向和大小,公式为LPI=amaxA×100%(0≤LPI≤100%)(2)式中amax———景观或某一种斑块类型中最大斑块的面积,hm2LPI———最大斑块指数,% 凝聚

soderayer的博客 13万+

当LightGBM推理遇上GPU:3种替代方案性能对比(含ONNX实战代码)

本文针对LightGBM官方不支持GPU推理的性能瓶颈,深度评测了RAPIDS cuML、ONNX Runtime GPU和Triton Inference Server三种GPU加速推理替代方案。通过详尽的性能对比和实战代码,为高并发、低延迟的在线预测场景提供了清晰的选型指南,帮助工程师打破推理性能枷锁,实现显著的吞吐量提升。

salt9的博客 813

Dotnet专业组件开发揭密2

<br /><br />本篇要讲述的是System.ComponentModel空间里最神奇的类,也是最重要的类,几乎所有的高级控件设计人员都必需掌握的类—TypeDescriptor。它的作用类似于反射,但是它是可以动态更改类信息的!虽然我们可能很少碰到直接使用它的情况,但是它的原理必须理解,这样你才不会对VS中一些机制产生疑问。<br />我们知道元数据可以说是Dotnet的基础,一旦编译后,就不能更改,而我们经常使用System.Reflection命名空间里的一些类来查看这些元数据,但是我们并没有办

溪风的专栏 700

工业产线瑕疵检测:基于 YOLO 的自动化质检系统实战

从工业瑕疵数据集构建到模型训练,从桌面检测界面到产线适用性优化,本文覆盖了一套工业质检系统的完整路线。这个场景的核心评价指标不是最高精度,而是在保证 recall ≥ 0.95 的前提下尽可能压低 false positive——因为漏检的直接成本(客户投诉、质量事故)远高于误报的成本(人工复检)。部署时先设一个偏低的置信度阈值确保覆盖,再通过持续收集人工复检数据来逐步调优。

m0_71589036的博客 66

ICustomTypeDescriptor接口

ICustomTypeDescriptor接口 Dotnet专业组件开发揭密 转载于:https://www.cnblogs.com/lky001/archive/2009/03/25/1421492.html

weixin_33916256的博客 560

展锐 Android 15 无听筒方案删除配置

【代码】展锐 Android 15 无听筒方案删除配置。

m0_60898338的博客 165

Android Input——输入系统介绍(一)

Input 系统对于提供流畅、灵敏和一致的用户交互体验至关重要,它需要在不同的设备、场景和应用中保证输入事件的正确性、及时性和安全性。Android 输入系统是一个复杂但高效的设计,旨在处理来自各种输入设备(如触摸屏、键盘等)的用户交互,并将这些交互转换为应用程序可以理解和响应的形式。EventHub:输入系统的最底层,直接与硬件通信,监听和读取输入设备的原始事件。:从 EventHub 获取原始输入事件,对其进行解析,转化为更高层次的事件,以便上层应用或服务能够理解。

小旭的专栏 1708

C#揭密II(大师们在说些什么?)

C#揭密II(大师们在说些什么?)先声明这篇文章属于收藏性质的,推荐给那些喜欢dotNET技术的爱好者。这之前我曾转载了OReilly的一篇关于C#的访谈录。OReilly一向以技术和评论公见长,他们的编辑一般都有着很深的技术背景和功力(所以出的书也比较贵haha),所以那篇着重整个流行技术,有不少是和Java相关的;而这一篇都是MS内部的几个高手在交谈聊天,涉及的范围比上次的专访要广,里

ccBoy的专栏 1825

基于Matlab的无迹卡尔曼滤波惯性导航与DVL组合导航

航天航空领域中的惯性导航是一种基于惯性测量单元(Inertial Measurement Unit,IMU)的导航方法,可以提供航向、速度和位置等信息。深度/速度测量器(Doppler Velocity Log,DVL)是一种常用的传感器,可用于测量水下航行器的速度。通过将DVL与无迹卡尔曼滤波相结合,可以实现高精度的组合导航。本文介绍了基于Matlab的无迹卡尔曼滤波(UKF)惯性导航与DVL组合导航的方法。以上是一种简化的示例代码,您可以根据实际应用需求进行相应的修改和优化。

DevSavantX的博客 416

解决用Visual Web Developer 2005编译asp.net 2.0项目时无dll文件的问题

   解决用Visual Web Developer 2005编译asp.net 2.0项目时无dll文件的问题     前段时间下载了Visual Web Developer 2005 Bate 2,想学习ASP.net 2.0。开发了一个网站,编译时发现这个东西跟VS2003不太一样,编译后项目中没有dll文件。昨天无意中发现了一本叫《Asp.net 2.0 大揭密》的书,翻了一下,发现里面有

Anpuso的专栏 2183

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

国产自主研发编程语言火了,同行十二年,不知Python是木兰?

1月17号有媒体称,一款面向智能物联网和编程教育的号称自主研发语言横空出世,名为【Mulan 】。消息一出,引起了众多争议。但有知乎网友发现,下载的程序包解包后——是个 Python?何...

dotNET跨平台 940

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: Dotnet专业组件开发揭密(一)
下一篇: Dotnet专业组件开发揭密(三)
BlueDog
博客等级 码龄27年 104粉丝 62原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值