一、组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1、类型创建RegisterType AutoFac能够通过反射检查一个类型,选择一个合适的构造函数,创造这个对象的实例。主要通过RegisterType<T>() 和 RegisterType(Type) 两个方法以这种方式建立。 ContainerBuilder使用 As() 方法将Component封装成了服务使用。
1 2 |
builder.RegisterType<AutoFacManager>(); builder.RegisterType<Worker>().As<IPerson>(); |
2、实例创建
1 |
builder.RegisterInstance<AutoFacManager>(new AutoFacManager(new Worker())); |
单例 提供示例的方式,还有一个功能,就是不影响系统中原有的单例:
1 |
builder.RegisterInstance(MySingleton.GetInstance()).ExternallyOwned(); //将自己系统中原有的单例注册为容器托管的单例 |
这种方法会确保系统中的单例实例最终转化为由容器托管的单例实例。 3、Lambda表达式创建 Lambda的方式也是Autofac通过反射的方式实现
1 2 |
builder.Register(c => new AutoFacManager(c.Resolve<IPerson>())); builder.RegisterType<Worker>().As<IPerson>(); |
4、程序集创建 程序集的创建主要通过RegisterAssemblyTypes()方法实现,Autofac会自动在程序集中查找匹配的类型用于创建实例。
1 2 |
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()); //在当前正在运行的程序集中找 builder.RegisterType<Worker>().As<IPerson>(); |
5、泛型注册 泛型注册通过RegisterGeneric() 这个方法实现,在容易中可以创建出泛型的具体对象。
1 2 3 4 5 6 |
//泛型注册,可以通过容器返回List<T> 如:List<string>,List<int>等等 builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope(); using (IContainer container = builder.Build()) { IList<string> ListString = container.Resolve<IList<string>>(); } |
6、默认的注册 如果一个类型被多次注册,以最后注册的为准。通过使用PreserveExistingDefaults() 修饰符,可以指定某个注册为非默认值。
1 2 3 4 5 6 7 8 9 |
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<AutoFacManager>(); builder.RegisterType<Worker>().As<IPerson>(); builder.RegisterType<Student>().As<IPerson>().PreserveExistingDefaults(); //指定Student为非默认值 using (IContainer container = builder.Build()) { AutoFacManager manager = container.Resolve<AutoFacManager>(); manager.Say(); //输出我是一个工人 } |
如果不使用PreserveExistingDefaults(),那么将输出“我是一个学生”。 二、服务 Autofac有三种典型的方式区分服务,同一个服务的不同实现可以由类型,名称和键区分。 1、类型 类型是描述服务的基本方法
1 |
builder.RegisterType<Worker>().As<IPerson>(); //IPerson类型的服务和Worker的组件连接起来,这个服务可以创建Worker类的实例 |
并且上面的服务在自动装备中也有效
1 |
AutoFacManager manager = container.Resolve<AutoFacManager>(); |
2、名字 服务可以进一步按名字识别。使用这种方式时,用 Named()注册方法代替As()以指定名字:
1 |
builder.RegisterType<Worker>().Named<IPerson>("worker"); |
使用Name可以检索服务创建实例:
1 |
IPerson p = container.ResolveNamed<IPerson>("worker"); |
ResolveNamed()只是Resolve()的简单重载,指定名字的服务其实是指定键的服务的简单版本。 3、键 有Name的方式很方便,但是值支持字符串,但有时候我们可能需要通过其他类型作键。 例如,使用枚举作为key:
1 |
public enum DeviceState { Worker, Student } |
使用key注册服务,通过Keyed<T>()方法:
1 |
builder.RegisterType<Student>().Keyed<IPerson>(DeviceState.Student); |
显式检索 使用key检索服务以创建实例,通过ResolveKeyd()方法:
1 |
IPerson p = container.ResolveKeyed<IPerson>(DeviceState.Student); |
ResolveKeyd()会导致容器被当做 Service Locator使用,这是不被推荐的。应该使用IIndex type替代。 IIndex索引 Autofac.Features.Indexed.IIndex<K,V>是Autofac自动实现的一个关联类型。component可以使用IIndex<K,V>作为参数的构造函数从基于键的服务中选择需要的实现。
1 2 3 4 5 6 7 |
builder.RegisterType<Student>().Keyed<IPerson>(DeviceState.Student); using (IContainer container = builder.Build()) { IIndex<DeviceState, IPerson> IIndex = container.Resolve<IIndex<DeviceState, IPerson>>(); IPerson p = IIndex[DeviceState.Student]; p.Say(); //输出我是一个学生 } |
IIndex中第一个泛型参数要跟注册时一致,在例子中是DeviceState枚举。其他两种注册方法没有这样的索引查找功能,这也是为什么设计者推荐Keyed注册的原因之一。 三、自动装配 从容器中的可用服务中选择一个构造函数来创造对象,这个过程叫做自动装配。这个过程是通过反射实现的,所以实际上容器创造对象的行为比较适合用在配置环境中。 1、选择构造函数 Autofac默认从容器中选择参数最多的构造函数。如果想要选择一个不同的构造函数,就需要在注册的时候就指定它。
1 |
builder.RegisterType(typeof(Worker)).UsingConstructor(typeof(int)); |
这种写法将指定调用Worker(int)构造函数,如该构造函数不存在则报错。 2、额外的构造函数参数 有两种方式可以添加额外的构造函数参数,在注册的时候和在检索的时候。在使用自动装配实例的时候这两种都会用到。 注册时添加参数 使用WithParameters()方法在每一次创建对象的时候将组件和参数关联起来。
1 2 |
List<NamedParameter> ListNamedParameter = new List<NamedParameter>() { new NamedParameter("Id", 1), new NamedParameter("Name", "张三") }; builder.RegisterType<Worker>().WithParameters(ListNamedParameter).As<IPerson>(); |
在检索阶段添加参数 在Resolve()的时候提供的参数会覆盖所有名字相同的参数,在注册阶段提供的参数会覆盖容器中所有可能的服务。 3、自动装配 至今为止,自动装配最大的作用就是减少重复配置。许多相似的component无论在哪里注册,都可以通过扫描使用自动装配。
1 |
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).As<IPerson>(); |
在需要的时候,依然可以创建指定的构造函数创建指定的类。
1 |
builder.Register(c => new Worker(2,"关羽")); |
四、程序集扫描 1、扫描 Autofac可以使用约定在程序集中注册或者寻找组件。 Autofac可以根据用户指定的规则在程序集中注册一系列的类型,这种方法叫做convention-driven registration或者扫描。
1 |
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Manager")); |
[…]
View Details最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来。 十年河东十年河西,莫欺少年穷 学无止境,精益求精 今天有点胡思乱想,想遍历MVC Model的属性并取值: 这个方法还是很简单的,通过反射即可遍历属性,我总结的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace WeiXinApi.CommonCS { public class ForeachClass { /// <summary> /// C#反射遍历对象属性 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="model">对象</param> public static void ForeachClassProperties<T>(T model) { Type t = model.GetType(); PropertyInfo[] PropertyList = t.GetProperties(); foreach (PropertyInfo item in PropertyList) { string name = item.Name; object value = item.GetValue(model, null); } } } } |
下面我们来简单测试下: 新建Model如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class AddressInfo { public int Id { get; set; } public string userName { get; set; } public string userTel { get; set; } public string Addressdetail { get; set; } public int isMoren { get; set; } public AddressInfo() { Id = 1; userName = "陈卧龙"; userTel = "1813707015*"; Addressdetail = "江苏省苏州市工业园区国际科技园"; isMoren = 1; } } |
调用如下:
1 2 3 4 5 6 7 8 9 |
public partial class index : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //Response.Redirect("/Home/Login"); AddressInfo model = new AddressInfo(); ForeachClass.ForeachClassProperties<AddressInfo>(model); } } |
测试结果如下: 经过测试,我们可以得到对象的各个属性及对应的值、 其实这块内容输入C# 反射系列,小弟也是误打误撞,撞入了C# 反射,索性每天学一点 from:https://www.cnblogs.com/chenwolong/p/fanshe.html
View Details
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 |
public class PP { public string a { get; set; } public string b { get; set; } public string c { get; set; } } class Program { static void Main(string[] args) { Hashtable ht = new Hashtable(); ht.Add("a", "utf8"); ht.Add("b", "xxxx"); ht.Add("c", "xxxx"); PP config = new PP(); PropertyInfo[] propertys = config.GetType().GetProperties(); foreach (PropertyInfo property in propertys) { for (int i = 0; i < ht.Count; i++) { property.SetValue(config, ht[property.Name].ToString(), null); } } Console.WriteLine(config.a+"\t"+config.b); Console.ReadLine(); } } |
from:https://www.cnblogs.com/yanglang/p/6830982.html
View Details解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<VSTemplate Version="2.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"> <TemplateData> <Name>DD373.Demo</Name> <Description>a DD373 Demo 16</Description> <Icon>__TemplateIcon.jpg</Icon> <ProjectType>CSharp</ProjectType> </TemplateData> <TemplateContent> <ProjectCollection> <ProjectTemplateLink ProjectName="$projectname$.Access" CopyParameters="true">DD373.Demo.Access\MyTemplate.vstemplate</ProjectTemplateLink> <ProjectTemplateLink ProjectName="$projectname$.Entity" CopyParameters="true">DD373.Demo.Entity\MyTemplate.vstemplate</ProjectTemplateLink> </ProjectCollection> </TemplateContent> </VSTemplate> |
其中一个解决方案:
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 |
<VSTemplate Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project"> <TemplateData> <Name>DD373.Demo.Access</Name> <Description>Access</Description> <ProjectType>CSharp</ProjectType> <ProjectSubType> </ProjectSubType> <SortOrder>1000</SortOrder> <CreateNewFolder>true</CreateNewFolder> <DefaultName>DD373.Demo.Access</DefaultName> <ProvideDefaultName>true</ProvideDefaultName> <LocationField>Enabled</LocationField> <EnableLocationBrowseButton>true</EnableLocationBrowseButton> <Icon>__TemplateIcon.jpg</Icon> <PreviewImage>__PreviewImage.jpg</PreviewImage> </TemplateData> <TemplateContent> <Project TargetFileName="DD373.Demo.Access.csproj" File="DD373.Demo.Access.csproj" ReplaceParameters="true"> <Folder Name="Properties" TargetFolderName="Properties"> <ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem> </Folder> <ProjectItem ReplaceParameters="true" TargetFileName="User.cs">User.cs</ProjectItem> </Project> </TemplateContent> </VSTemplate> |
View Details
若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档。 在对模板进行实例化时,您可以通过模板的参数,替换模板的关键部分的值,如类名和命名空间。 当用户在“新建项目”或“添加新项”对话框中单击“确定”时,这些参数将由后台运行的模板向导替换。 声明和启用模板参数 模板参数以 $parameter$ 格式进行声明。 例如: $safeprojectname$ $guid1$ $guid5$ 启用模板中的参数替换 在模板的 .vstemplate 文件中,定位到与要为其启用参数替换的项对应的 ProjectItem 元素。 将 ProjectItem 元素的 ReplaceParameters 特性设置为 true。 在项目项的代码文件中,在合适的位置包括参数。 例如,下面的参数指定用于文件中的命名空间的安全项目名称:
1 |
namespace $safeprojectname$ |
保留的模板参数 下表列出了可供所有模板使用的保留的模板参数。 说明 模板参数区分大小写。 Parameter 描述 clrversion 公共语言运行时 (CLR) 的当前版本。 GUID [1-10] 用于替换项目文件中的项目 GUID 的 GUID。 最多可以指定 10 个唯一的 GUID(例如,guid1))。 itemname 用户在添加新项对话框中提供的名称。 machinename 当前的计算机名称(例如,Computer01)。 projectname 用户在新建项目对话框中提供的名称。 registeredorganization HKLM\Software\Microsoft\Windows NT\CurrentVersion\RegisteredOrganization 中的注册表项值。 rootnamespace 当前项目的根命名空间。 此参数仅适用于项目模板。 safeitemname 用户在“添加新项”对话框中提供的名称,名称中移除了所有不安全的字符和空格。 safeprojectname 用户在“新建项目”对话框中提供的名称,名称中移除了所有不安全的字符和空格。 time 以 DD/MM/YYYY 00:00:00 格式表示的当前时间。 SpecificSolutionName 解决方案的名称。 当“创建解决方案的目录”被选中,SpecificSolutionName 具有解决方案的名称。 当“创建解决方案的目录”没有被选中,SpecificSolutionName是空。 userdomain 当前的用户域。 username 当前的用户名。 webnamespace 当前网站的名称。 在 Web 窗体模板中使用此参数以确保类名称是唯一的。 如果网站位于 Web 服务器的根目录下,则此模板参数将解析为 Web 服务器的根目录。 […]
View Details若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档。 指定多项目模板中一个项目的 .vstemplate 文件的路径。 语法
1 2 3 |
<ProjectTemplateLink ProjectName="Name"> PathToTemplateFile </ProjectTemplateLink> |
特性和元素 以下各部分描述了特性、子元素和父元素。 特性 特性 描述 ProjectName 可选特性。 指定多项目模板中每一个项目的名称。 新项目对话框中不能向单个项目分配名称。 CopyParameters 使主要组模板中的所有变量可复制到每个链接模板。 链接模板中的参数具有前缀 "$ext_*$"。 例如,如果在父组模板参数$projectname$具有值exampleproject1 则轮到,当模板链接获取又要执行,它将获取参数$ext_projectname$,这是一份$projectname$父组模板中的参数。 这使链接模板能够共享一些只能在父组模板中方便地创建的公用参数。 此特性为可选特性,未包含此特性时,它将自动默认为 false。 在 Visual Studio 2013 Update 2 中引入。 若要引用正确的产品版本,请参阅引用程序集提供的 Visual Studio 2013 SDK Update 2。 父元素 元素 描述 ProjectCollection 指定多项目模板的组织和内容。 SolutionFolder 对多项目模板中的项目进行分组。 文本值 需要一个文本值。 此文本指定模板的 .vstemplate 文件的路径。 多项目模板用作两个或多个项目的容器。 ProjectTemplateLink 元素用于指定模板中一个项目的 .vstemplate 文件的位置。 对于多项目模板中的每个项目,此模板的 .vstemplate 文件中都含有一个对应的 ProjectTemplateLink 元素。 有关多项目模板的详细信息,请参阅如何︰ 创建多项目模板。 此示例演示一个简单的多项目 .vstemplate 根文件。 在此示例中,模板包含两个项目:My Windows Application 和 My Class Library。ProjectName 元素的 ProjectTemplateLink 特性可为 Visual Studio 设置要分配给此项目的名称。 如果不存在 ProjectName 特性,则会使用 .vstemplate 文件的名称作为项目名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<VSTemplate Version="3.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"> <TemplateData> <Name>Multi-Project Template Sample</Name> <Description>An example of a multi-project template</Description> <Icon>Icon.ico</Icon> <ProjectType>VisualBasic</ProjectType> </TemplateData> <TemplateContent> <ProjectCollection> <ProjectTemplateLink ProjectName="My Windows Application"> WindowsApp\MyTemplate.vstemplate </ProjectTemplateLink> <ProjectTemplateLink ProjectName="My Class Library" CopyParameters="true"> ClassLib\MyTemplate.vstemplate </ProjectTemplateLink> </ProjectCollection> </TemplateContent> </VSTemplate> |
from:https://msdn.microsoft.com/zh-cn/library/ms171398.aspx
View Details本文分2部分 第一为自定义多项目模板 第二为vs add-in开发 效果图 1.自定义模板 2. 工具菜单 3.窗口 4.工程 5.文件 … 一. 多项目模板 单项目模板做起来很简单 选中一个项目在文件一栏中选中导出模板 然后选择项目模板 在最后一项向导会给出你的输出路径,一般都是系统的用户文档路径+\Visual Studio 2010\My Exported Templates 在对应目录下会生成你对应的项目模板压缩包 我们生成2个项目的模板文件 然后做一个多项目模板 我们解压2个模板文件并且放进一个新建的名称为MaoyaTemplates的文件夹 剪切到Visual Studio 2010\Templates\ProjectTemplates路径下 新建模板文件MyTemplate.vstemplate 根据要定义的模板内容 修改文件 然后将整个文件夹压缩成zip文件即可 在TemplateData可以定义一些自己需要的信息 例如icon定义你的模板图标 把图标文件放在相对路径即可 然后重新打开vs 即可看到刚才作成的模板 打开以后就是定义的2个demo工程 相当简单 这样就不用每次来新项目都去copy代码了 二 vs插件 概念性的东西可以参考 http://msdn.microsoft.com/zh-cn/library/bb384200.aspx vs插件可以帮助或者优化你在vs开发过程的大部分窗口 它可以针对文件 针对项目 针对窗口 甚至针对不同的后缀做不同的处理 下面图文+代码介绍开发步骤(vs2010) 选择插件项目 进入向导根据自己的场景选择即可 中间向导过程略过 最后一步 完成向导后 默认工程框架如下 最关键的就是connect.cs文件 Connect 继承了2个类 IDTExtensibility2, IDTCommandTarget IDTExtensibility2 包含在实现接口时用作事件的方法。 每当发生影响某个外接程序的事件时(如加载或卸载该外接程序时)以及对该外接程序进行任何更改时,Visual Studio 都会调用这些方法。 IDTCommandTarget 接口使开发者得以在环境中实现命名命令。 并且以定义命令状态或执行命令。 每个方法的描述 中文版可以参考msdn http://msdn.microsoft.com/zh-cn/library/extensibility.idtextensibility2.aspx http://msdn.microsoft.com/zh-cn/library/envdte.idtcommandtarget.aspx 其中我们作为入门开发 需要关注得的是 OnConnection 为IDTExtensibility2的 main 方法,这是因为每次加载外接程序时都会调用该方法。 该方法为外接程序在加载时的入口点,因此可以将要在外接程序启动时运行的任何代码放置在此处(或调用任何其他函数)。 1 2 3 4 5 6 void OnConnection( Object Application, ext_ConnectMode ConnectMode, Object […]
View Details熟悉IoC容器的都知道,在开发过程中,最郁闷的莫过于当你新增一个Service时,你需要对该Service进行注册,有的是使用代码注入,有的是XML配置注入,不管是哪种类型的注入,经常会出现开发人员忘记注入的情况, 如果你的页面是直接发送请求的,那么会得到类似于如下页面的错误: <- _<- 如果该服务是用于AJAX请求实用的,那么你就悲剧了,因为页面只是没反应,只有查看错误日志了。 于是我试着去想办法去避免每次的服务都需要注入,而是系统自动注入。 红色线条框住的地方就是自动注入的代码实现。很高兴Autofac提供一个RegisterAssemblyTypes方法。它回去扫描所有的dll并把每个类注册为它所实现的接口。。。。 既然能够自动注入,那么接口和类的定义一定要有一定的规律。 从上面的代码可以看到baseType这个变量,它是IDependency接口的类型。 IDependency接口如下: 其他任何的接口都需要继承这个接口,例如我们定义一个接口IModelCar: IModelCar的实现类: 自动注入原理说明: 首先我们去找到所有Dll,再去找到实现了IDependency接口的类,然后使用RegisterAssemblyTypes进行注入。 在Controller中调用试试: 可以看到_carmodel解析后为ModelCar的实例。。 Demo下载: https://github.com/nicholaspei/MvcApplication5 from: https://www.cnblogs.com/n-pei/archive/2013/01/24/2875674.html
View Details微信内置浏览器(WebView)中特有的javascript API(javascript Interface),随着微信官方的调整,部分API已经不能直接使用,比如类似直接分享到朋友圈WeixinJSBridge.invoke(shareTimeline,data,callback) 这样的功能,直接调用,会得到一个访问拒绝的response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function WeiXinShareBtn() { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } alert("请先通过微信搜索 wow36kr 添加36氪为好友,通过微信分享文章 "); } else { WeixinJSBridge.invoke('shareTimeline', { "title": "36氪", "link": "http://www.36kr.com", "desc": "关注互联网创业", "img_url": "http://www.36kr.com/assets/images/apple-touch-icon.png" }); } } |
此方法已过时,被微信禁用了。只能用微信官方的接口 1、前台脚本
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<script src="../Scripts/jquery-1.10.2.js"></script> <script src="//res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript"></script> <script> wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '<%=appid%>', // 必填,公众号的唯一标识 timestamp: '<%=timestamp%>', // 必填,生成签名的时间戳 nonceStr: '<%=nonce%>', // 必填,生成签名的随机串 signature: '<%=signature%>',// 必填,签名,见附录1 jsApiList: ["checkJsApi", "onMenuShareTimeline", "onMenuShareAppMessage"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 //当前客户端版本是否支持指定JS接口,分享到朋友圈,分享给朋友 }); wx.ready(function () { wx.checkJsApi({ jsApiList: ['chooseImage'], // 需要检测的JS接口列表,所有JS接口列表见附录2, success: function (res) { alert(JSON.stringify(res)); // 以键值对的形式返回,可用的api值true,不可用为false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} } }); //朋友圈 wx.onMenuShareTimeline({ title: '春天里的健康', // 分享标题 desc: '春天里的健康春天里的健康春天里的健康', // 分享描述 link: '<%=thisUrl%>', // 分享链接 imgUrl: 'https://imgsa.baidu.com/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=c31e0863bf315c60579863bdecd8a076/4034970a304e251fb62a408ea486c9177e3e53e2.jpg', success: function (res) { alert('已分享'); }, cancel: function (res) { alert('已取消'); }, fail: function (res) { alert(JSON.stringify(res)); } }); //朋友 wx.onMenuShareAppMessage({ title: '春天里的健康', // 分享标题 desc: '春天里的健康春天里的健康春天里的健康', // 分享描述 link: '<%=thisUrl%>', // 分享链接 imgUrl: 'https://imgsa.baidu.com/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=c31e0863bf315c60579863bdecd8a076/4034970a304e251fb62a408ea486c9177e3e53e2.jpg', // 分享图标 type: '', // 分享类型,music、video或link,不填默认为link dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数 alert("分享成功"); }, cancel: function () { // 用户取消分享后执行的回调函数 alert("取消分享"); } }); }); </script> |
2、后台代码
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
using Senparc.Weixin.MP.Containers; using Senparc.Weixin.MP.Helpers; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace jkmobile.share { public partial class ReportShare : System.Web.UI.Page { public string appid = "", timestamp="", nonce="",thisUrl="", signature=""; protected void Page_Load(object sender, EventArgs e) { WXShareModel wxmodel = new WXShareModel(); wxmodel = Ge_WXShareModel(); appid = wxmodel.appid; timestamp = wxmodel.timestamp; nonce = wxmodel.nonce; thisUrl = wxmodel.thisUrl; signature = wxmodel.signature; } #region 微信分享 public WXShareModel Ge_WXShareModel() { string APPID = ConfigurationManager.AppSettings["appid"]; string secret = ConfigurationManager.AppSettings["secret"]; WXShareModel fxModel = new WXShareModel(); fxModel.appid = APPID; fxModel.timestamp = JSSDKHelper.GetTimestamp(); fxModel.nonce = JSSDKHelper.GetNoncestr(); fxModel.thisUrl = Request.Url.ToString().Split('#')[0]; fxModel.ticket = JsApiTicketContainer.TryGetJsApiTicket(APPID, secret); //最后一个参数url,必须为当前的网址 var signature = JSSDKHelper.GetSignature(fxModel.ticket, fxModel.nonce, fxModel.timestamp, fxModel.thisUrl); fxModel.signature = signature; return fxModel; } #endregion } public class WXShareModel { /// <summary> /// 公众号的唯一标识 /// </summary> public string appid { get; set; } /// <summary> /// 生成签名的随机串 /// </summary> public string nonce { get; set; } /// <summary> /// 生成签名的时间戳 /// </summary> public string timestamp { get; set; } /// <summary> /// 签名 /// </summary> public string signature { get; set; } public string ticket { get; set; } /// <summary> /// 分享的地址 /// </summary> public string thisUrl { get; set; } } } |
请引用微信官方封装好的dll Senparc.Weixin.dll Senparc.Weixin.MP.dll from:https://blog.csdn.net/lybwwp/article/details/70172232
View Details随着 AI 技术快速发展,各种理论与实践层出不穷,它正在迅速改变我们生活中几乎每一个领域,从我们如何交流到用于交通的手段。作为开发者或者学习者,在开始构建机器学习应用程序之前,从众多开源项目中选择一项应该是一个艰巨的任务,日前,有网友在博客总结了 8 种最好的开源 AI 技术,为机器学习开发者指明道路。 1、Tensorflow TensorFlow 是谷歌为支持其研究和生产目标创建的项目,于 2015 年发布,它是一款开源机器学习框架,易于在各种平台上使用和部署。它是机器学习中维护得最好和广泛使用的框架之一,目前已被多家公司广泛使用,包括 Dropbox、eBay、Intel、Twitter 和 Uber。 TensorFlow 可用于 Python、C++、Haskell、Java、Go、Rust 以及 JavaScript,同时还有其它编程语言的第三方软件包可使用。该框架允许开发者使用流图开发神经网络等计算模型。 2、Keras Keras 是一个开源机器学习库,最初于 2015 年发布,旨在简化深度学习模型的创建。它使用 Python 编写而成,可以部署在其它人工智能技术之上,如 TensorFlow、Microsoft Cognitive Toolkit(CNTK)和Theano。 Keras 以其对用户友好、模块化和易扩展性而闻名。它可以实现简单快速的原型设计,同时支持卷积网络和循环网络,并且能够在 CPU 和 GPU 上运行达到最佳状态。 3、Scikit-learn 最初于 2007 年发布的 Scikit-learn 是为机器学习开发的开源库,这个传统的框架是用 Python 编写的,它基于另外三个开源项目 Matplotlib、NumPy 和 SciPy 设计而成,专注于数据挖掘和数据分析,包含了几种机器学习模型,包括分类、回归、聚类和降维。 4、Microsoft Cognitive Toolkit 最初于 2016 年发布的 Microsoft Cognitive Toolkit ,之前称为 CNTK,它是一种 AI 解决方案,可让您将机器学习项目提升到一个新的水平。微软表示,开源框架能够“训练深度学习算法,以便像人脑一样工作”。 Microsoft Cognitive Toolkit 的一些重要功能包括高度优化的组件,能够处理来自 Python、C++ 或 BrainScript 的数据,提供高效的资源利用,轻松与 Microsoft Azure 集成以及与 NumPy 进行互操作。 5、Theano Theano 最初于 2007 年发布,它是一个开源的 Python 库,允许开发者轻松地构建各种机器学习模型。由于它是最早的 AI 库之一,被视为推动深度学习发展的行业标准。 Theano 的特征是可以简化定义、优化和评估数学表达式的过程,它能够将您的数据结构转换为与 NumPy、BLAS 等本地库以及本地代码集成的非常高效的代码。此外,它针对 GPU 进行了优化,并且具有广泛的代码测试功能。 […]
View Details