C#-DllImport使用方法详解

关键字:C# DllImport

DllImport是 System.Runtime.InteropServices 命名空间下的一个属性类,其功能是提供从 非托管DLL (托管/非托管是微软的.net framework中特有的概念,其中,非托管代码也叫本地(native)代码。
与Java中的机制类似,也是先将源代码编译成中间代码(MSIL,Microsoft Intermediate Language),然后再由.net中的CLR将中间代码编译成机器代码。)导出的函数的必要调用信息.

相关连接:https://blog.csdn.net/aidem_brown/article/details/79820160

DllImport属性应用于方法,要求最少要提供包含入口点的dll的名称

读写INI配置文件文章中,使用了此方法

C#-读取修改App.config

读取操作

由于1处是有 key 的,所以读取的时候只需要:

string sourceFolder = ConfigurationManager.AppSettings["sourceFolder"];

而 2 处(数据库连接字符串)没有key,所以读取的时候:

string CustomDB = ConfigurationManager.ConnectionStrings["CustomDB"].ConnectionString;

当然,如果你需要多个连接字符串,可以像3处一样,增加即可

写入操作

//写入<add>元素的Value
    config.AppSettings.Settings["name"].Value = "fx163";

    //增加<add>元素
    config.AppSettings.Settings.Add("url", "https://www.guxiaonan.com");

    //删除<add>元素
    config.AppSettings.Settings.Remove("name");

    //一定要记得保存,写不带参数的config.Save()也可以
    config.Save(ConfigurationSaveMode.Modified);

    //刷新,否则程序读取的还是之前的值(可能已装入内存)
    System.Configuration.ConfigurationManager.RefreshSection("appSettings");

C#-NameValueCollection快速转QueryString

How to convert NameValueCollection to a (Query) String

/// <summary>
/// Constructs a QueryString (string).
/// Consider this method to be the opposite of "System.Web.HttpUtility.ParseQueryString"
/// </summary>
public static string ConstructQueryString(NameValueCollection parameters)
{
	List<string> items = new List<string>();

	foreach (string name in parameters)
		items.Add(string.Concat(name, "=", System.Web.HttpUtility.UrlEncode(parameters[name])));

	return string.Join("&", items.ToArray());
}

https://leekelleher.com/2008/06/06/how-to-convert-namevaluecollection-to-a-query-string/

转为Json

Headers = JsonConvert.SerializeObject(Request.Headers)

快速

string.Join(",",Request.Headers.AllKeys.SelectMany(Request.Headers.GetValues, (k, v) =>new { key = k, value = v }));

var headersString = string.Join(
    Environment.NewLine,
    Request.Headers.AllKeys.SelectMany(
        Request.Headers.GetValues,
        (k, v) => k + ": " + v));

快速按行输出

string headersString = string.Join("\r\n", context.Request.Headers.Select(s =>s.Key + ":" + s.Value.ToString()));

使用换行符号作为连接

C#–读写INI配置文件-INI配置文件格式

关键字:ini文件格式

如何读写:

https://www.cnblogs.com/ashbur/p/12020507.html

ini配置文件格式

https://blog.csdn.net/a123441/article/details/90668032

首先文件扩展名

配置文件.ini

格式

ini配置文件由节、键、值组成

【参数】(键=值):

INI所包含的最基本的“元素”就是参数(parameter),每个参数都有一个name和一个value,name和value由等号“=”隔开,name在等号的左边。如:

name=value

所有的参数都是以节(section)为单位结合在一起的。
所有的section名称都是独占一行,并且section名字都被方括号包围着([和])。在section声明后的所有parameters都属于该section。
一个section没有明显的结束标识符,
一个section的开始就是上一个section的结束,或者是文件结束

[section]

最好用的ini配置文件辅助类

public class IniFileHelper
{
    #region API函数声明
 
    [DllImport("kernel32")]//返回0表示失败,非0为成功
    private static extern long WritePrivateProfileString(string section,string key,
        string val,string filePath);
 
    [DllImport("kernel32")]//返回取得字符串缓冲区的长度
    private static extern long GetPrivateProfileString(string section,string key,
        string def,StringBuilder retVal,int size,string filePath);
 
 
    #endregion
 
    #region 读Ini文件
 
    public static string ReadIniData(string Section,string Key,string NoText,string iniFilePath)
    {
        if(File.Exists(iniFilePath))
        {
            StringBuilder temp = new StringBuilder(1024);
            GetPrivateProfileString(Section,Key,NoText,temp,1024,iniFilePath);
            return temp.ToString();
        }
        else
        {
            return String.Empty;
        }
    }
 
    #endregion
 
    #region 写Ini文件
 
    public static bool WriteIniData(string Section,string Key,string Value,string iniFilePath)
    {
        if(!File.Exists(iniFilePath))
        {
            using(FileStream fs=new FileStream(iniFilePath,FileMode.Create,FileAccess.Write))
            {
                fs.Close();
            }
        }
        if(File.Exists(iniFilePath))
        {
            long OpStation = WritePrivateProfileString(Section,Key,Value,iniFilePath);    
            if(OpStation == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        else
        {
            
            return false;
        }
    }
 
    #endregion
}

读取节点信息:

IniFileHelper.ReadIniData("config", "lastPath", "", System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lahuseo.ini"));

程序自动到当前执行程序的根目录找文件名为”lanhuseo.ini“的文件,节点组为config,节点key为lastpath的值

更新节点信息:

IniFileHelper.WriteIniData("config", "lastPath"
                , txtLogDirOrFile.Text.Trim()
                , System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lahuseo.ini"));

这样存的文件内容为:

[config]
lastPath=C:\Users\Administrator\Desktop\新建文件夹\W3SVC12

这里用到用到了DllImport直接用了windows系统内核的kernel32.dll的现成的两个方法,WritePrivateProfileString和GetPrivateProfileString。
如果在写文件没有指定的文件会自动创建一个相应的ini文件,在读的时候没有文件直接返回空,当然这里你可以根据你的需要修改



C#-面向对象-OOP基础概念

1.方法的签名是指 ?
答:方法名和该方法的参数列表,类型,大小,位置。
 
2.请简述C#中结构与类的区别?
答:数据类型不同:结构是值类型,值类型在堆栈上分配地址,所有的基类型都是结构类型,类是引用类型,引用类型在堆上分配地址。
继承性:结构不能从另外一个结构或者类继承,本身也不能被继承,类完全可扩展的,除非显示的声明 sealed,否则类可以继承其他类和接口,自身也能被继承,虽然结构不能被继承 可是结构能够继承接口,方法和类继承接口一样
内部结构:结构没有默认的构造函数,但是可以添加构造函数 ,没有析构函数,没有 abstract 和 sealed(因为不能继承) ,不能有 protected 修饰符,可以不使用 new 初始化 ,在结构中初始化实例字段是错误的。类有默认的构造函数 ,有析构函数,可以使用 abstract 和 sealed,有 protected 修饰符,必须使用 new 初始化。
 
3 C#中类可以实现多继承吗?通过什么方式实现呢?
答:C#中类不能够多继承,必须通过接口实现。
 
4.继承是面向对象编程的一个重要的概念.请简述继承的概念和优点.
答:继承:一个类可以有能力直接从另一个类获得其代码和数据,派生类从基类那里获得其所有成员。
优点:使用继承无需从头开始创建新类,便可以在现有类的基础上添加新方法、属性和事件(事件是对用户操作)的响应。,既省时又省力。
 
5.说明base关键字、new关键字和override关键字各自的作用。
答:关键字base,用于派生类的构造函数显示调用基类构造函数。
new访问修饰符用于显示隐藏继承自基类的成员,即如果派生的类成员的名称与基类成员名称相同,new关键字会将派生类成员识别为一个全新的成员。
关键字override用于修改方法,具有override关键字修饰的方法是对基类中同名方法的新实现
 
6.override即 重写 是指重写基类的方法(方法的覆盖)。
 
7.override用来重写父类的方法,重载使用相同名的方法或操作符拥有不同类型的参数
 
8.关键字base 用于派生类的构造函数显示调用基类构造函数
 
9.一个类可以有能力直接从另一个类获得其代码和数据,派生类从基类那里获得其所有成员的是继承   。
 
10.调用基类构造函数,运用base关键字。
 
11.虚方法的关键字是virtual 。
 
12.C#提供virtual关键字,用于将方法定义为支持多态。
 
13.Override 关键字用于重写基类的虚拟方法。
 
14.面向对象的特征有封装 继承 多态.
 
15.抽象类的关键字是abstract
 
16.密封类的关键字是sealed。
 
17.抽象类的方法 可以 实现,接口的方法 必须 实现。
 
18.接口不能被实例化
 
19.类不可以多重继承 而接口可以
 
20.抽象类自身可以定义成员而接口不可以
 
21.一个类可以实现多个接口
 
22.虚方法 可以在派生类 重写,抽象方法 必须在每个非抽象的派生类中 重写。
 
23.如果Alpha类继承自BETA类,则Alpha类称为  派生类     ,BETA类称为   基类     。
 
24.有一个基类Person,一个接口Iteller。类Employee要同时继承类和接口,则其正确的写法应该是   public class Employee : Person,Itrller   
 
25.接口是一种引用类型,在接口中可以声明方法、属性、索引器和事件,但不可以声明公有的域或私有的成员变量。
 
26.Sealed修饰符是干什么的?
答:表示密封类,用于类时表明该类不能被继承,不能和abstract同时使用,因为这两个修饰符在含义上互相排斥,用于方法和属性时,表示该方法或属性不能再被继承,必须和override关键字一起使用,因为使用sealed修饰符的方法或属性肯定是基类中相应的虚成员
 
27.简述抽象类的定义以及在C#编程语言中,抽象类的作用是什么?
答: 有时,我们只需要继承某个特定类,但不需要实例化该类的对象。这样的类成为抽象基类。C#允许通过在类中添加abstract关键字来创建抽象基类。
   作用: 在抽象基类中,可以指定一个方法而不指定其代码主体。这意味着抽象基类保存着方法的定义,而方法的实际实现则写在派生类中
 
28.声明抽象方法注意一下几点?
答: 抽象基类除了抽象方法外,还可以包含已实现的方法。
    需要用abstract关键字来标识。
    的定义始终已分号结束。
 
29.要声明类或结构上的索引器,使用this关键字
 
30.属性是一个或两个代码,表示一个get访问器和/或一个set访问器。
 
31.属性的     set   访问器用于将值赋给类的私有实例变
 
32.简述属性的定义及其作用?
答:属性是一种用于访问对象或类的特性的成员,停供了数据的封装性和安全
性。
 
33.简述索引器的定义及其作用?
答:索引器是C#的简单组件,使用索引器,可以用索引数组的方式来索引对象,
索引器提供了与数组访问相类似的类成员访问方式。
 
34.简述索引器和属性之间的区别?
答:属性通过名称标识。索引器通过签名标识。    
    属性通过简单名称或成员访问来访问。索引器通过元素访问来访问。    
    属性可以为静态成员或实例成员。索引器必须为实例成员。    
    属性的get 访问器没有参数。 索引器的 get 访问器具有与索引器相同的形参
表。属性的 set 访问器包含隐式 value 参数。除了 value 参数外,索引器的 set
访问器还具有与索引器相同的形参表。
 
35.什么是迭代器,运用迭代器有什么好处。
答:迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使
能够在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。只
需提供一个迭代器,即可遍历类中的数据结构,它的优点就是可以是实现容器
类和自定义集合的循环。
 
36.委托的关键字是delegate 。
 
37.委托的参数和返回类型必须和调用函数一致
 
38.委托本身能够拥有一个签名 ,当它持有与它的签名  相匹配的方法的引用后,委托就可以和这个方法一样被调用
 
39.定义事件的关键字是event  。
 
40.定义一个多路委托有几个步骤
答: 定义一个委托类型
编写具有相同签名方法作为委托
创建委托对象,将它绑定到需要通过委托调用的第一个方法
创建另一个委托对象,绑定到下一个需要调用的方法
可用+,-,+=或-=操作符,合并成一个集成的多播委托
 
41.简述创建事件的过程
答:定义事件
给对象预订该事件
将该事件(当它发生时)通知订户
 
42.什么是多播委托?
答:多播委托也是一个委托,它可以调用多个方法,只要这些方法的签名与委托的定义相同。多播委托的概念是委托和事件编程之间的门槛,多播委托是通过对方法的委托进行组合而创建的。组合多个委托,可用+,-,+=或-=操作符。要让一个委托调用多个方法,可以用+或+=操作符为该委托增加方法。要减少一个多播委托持有的方法,可以使用-或-=操作符。
————————————————

C#-获取当前时间戳的几种方法

代码如下

第一种
        /// <summary> /// 获取当前时间戳
        /// </summary>
        /// <returns></returns>
        public string GetTimeStamp()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
第二种

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds).ToString();
        }

.Net中没有封装获取时间戳(UnixTime,相对于1970年1月1日凌晨的毫秒数)的方法。因此本人写了如下方法实现。

提醒在摸索中的朋友,注意方法中的四舍五入。关于讨论四舍五入的方法

DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));

DateTime nowTime = DateTime.Now;

long unixTime = (long)Math.Round((nowTime - startTime).TotalMilliseconds, MidpointRounding.AwayFromZero);

https://www.cnblogs.com/iack/p/3551709.html

C#中系统时间和UNIX时间戳互相转换

https://www.cnblogs.com/yuwentao/p/7232838.html

C#-操作符-?-单引号

最终结果 int? 单引号的含义
C#中不允许对值类型 赋值为空类型,但是赋值空类型有时候是非常有用的【和数据库对应】
”?(单问号)“修饰符,是System.Nullable的缩写形式,比如int?代表是可空的整形,例如:int? a = 1 或者 int? b=null。Nullable类型具有一个HasValue的bool类型只读属性,当Nullable类型实例的该属性为true时,则表示该实例是非空实例,包含一个已知值Value,HasValue为false时,访问Value属性将导致System.InvalidOperationException。