func委托代表有返回类型的委托
查看func的定义:
using system.runtime.compilerrvices;namespace system{ // // 摘要: // 封装一个方法,该方法具有两个参数,并返回由 tresult 参数指定的类型的值。 // // 参数: // arg1: // 此委托封装的方法的第一个参数。 // // arg2: // 此委托封装的方法的第二个参数。 // // 类型参数: // t1: // 此委托封装的方法的第一个参数的类型。 // // t2: // 此委托封装的方法的第二个参数的类型。 // // tresult: // 此委托封装的方法的返回值类型。 // // 返回结果: // 此委托封装的方法的返回值。 [typeforwardedfrom("system.core, version=3.5.0.0, culture=neutral, publickeytoken=b77a5c561934e089")] public delegate tresult func<in t1, in t2, out tresult>(t1 arg1, t2 arg2);}
你会发现,func其实就是有多个输出参数并且有返回值的delegate。
func至少0个输入参数,至多16个输入参数,根据返回值泛型返回。必须有返回值,不可void。
func<int> 表示没有输入参参,返回值为int类型的委托。
func<object,string,int> 表示传入参数为object, string ,返回值为int类型的委托。
func<object,string,int> 表示传入参数为object, string, 返回值为int类型的委托。
func<t1,t2,,t3,int> 表示传入参数为t1,t2,,t3(泛型),返回值为int类型的委托。
代码示例如下:
using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace fundemo{ class program { static void main(string[] args) { // 无参数,只要返回值 func<int> fun1 = new func<int>(funwithnopara); int result1= fun1(); console.writeline(result1); console.writeline("----------------------------"); func<int> fun2 = delegate { return 19; }; int result2 = fun2(); console.writeline(result2); console.writeline("----------------------------"); func<int> fun3 = () => { return 3; }; int result3 = fun3(); console.writeline(result3); console.writeline("----------------------------"); //有一个参数,一个返回值 func<int, int> fun4 = new func<int, int>(funwithpara); int result4 = fun4(4); console.writeline($"这里是一个参数一个返回值的方法,返回值是:{result4}"); console.writeline("----------------------------"); // 使用委托 func<int, string> fun5 = delegate (int i) { return i.tostring(); }; string result5 = fun5(5); console.writeline($"这里是一个参数一个返回值的委托,返回值是:{result5}"); console.writeline("----------------------------"); // 使用匿名委托 func<int, string> fun6 = (int i) => { return i.tostring(); }; string result6 = fun6(6); console.writeline($"这里是一个参数一个返回值的匿名委托,返回值是:{result6}"); console.writeline("----------------------------"); // 多个输入参数 func<int, string, bool> fun7 = new func<int, string, bool>(funwithmultipara); bool result7 = fun7(2, "2"); console.writeline($"这里是有多个输入参数的方法,返回值是:{result7}"); console.writeline("----------------------------"); // 使用委托 func<int, string, bool> fun8 = delegate (int i, string s) { return i.tostring().equals(s) ? true : fal; }; bool result8 = fun8(2, "abc"); console.writeline($"这里是有多个输入参数的委托,返回值是:{result8}"); console.writeline("----------------------------"); // 使用匿名委托 func<int, string, bool> fun9 = (int i, string s) => { return i.tostring().equals(s) ? true : fal; }; bool result9 = fun9(45, "ert"); console.writeline($"这里是有多个输入参数的匿名委托,返回值是:{result9}"); console.readkey(); } static int funwithnopara() { return 10; } static int funwithpara(int i) { return i; } static bool funwithmultipara(int i,string s) { return i.tostring().equals(s) ? true : fal; } }}
运行结果:
在下面的示例中,利用func委托封装数据库通用访问类。
using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.model{ public class bamodel { public int id { get; t; } }}
using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.model{ public class student : bamodel { public string name { get; t; } public int age { get; t; } public int x { get; t; } public string email { get; t; } }}
using funapplication.model;using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.idal{ public interface ibadal { t query<t>(int id) where t : bamodel; list<t> queryall<t>() where t : bamodel; int inrt<t>(t t) where t : bamodel; int update<t>(t t) where t : bamodel; int delete<t>(int id) where t : bamodel; }}
using system;using system.collections.generic;using system.linq;using system.reflection;using system.text;using system.threading.tasks;namespace funapplication.attributeextend{ public static class attributehelper { public static string getcolumnname(this propertyinfo prop) { if (prop.isdefined(typeof(columnattribute), true)) { columnattribute attribute = (columnattribute)prop.getcustomattribute(typeof(columnattribute), true); return attribute.getcolumnname(); } el { return prop.name; } } }}
using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.attributeextend{ [attributeusage(attributetargets.property)] public class columnattribute : attribute { public columnattribute(string name) { this._name = name; } private string _name = null; public string getcolumnname() { return this._name; } }}
using funapplication.idal;using funapplication.model;using system;using system.collections.generic;using system.configuration;using system.data.sqlclient;using system.linq;using system.text;using system.threading.tasks;using system.reflection;using funapplication.attributeextend;namespace funapplication.dal{ public class badal : ibadal { // 数据库链接字符串 private static string strconn = configurationmanager.connectionstrings["dbconnection"].connectionstring; public int delete<t>(int id) where t : bamodel { int result = 0; using (sqlconnection conn = new sqlconnection(strconn)) { string strsql = "delete from student where id=@id"; sqlparameter para = new sqlparameter("id", id); sqlcommand command = new sqlcommand(strsql, conn); command.parameters.add(para); conn.open(); result = command.executenonquery(); } return result; } public int inrt<t>(t t) where t : bamodel { int result = 0; using (sqlconnection conn = new sqlconnection(strconn)) { type type = typeof(t); var proparray = type.getproperties().where(p => p.name != "id"); string strsql = "inrt into student values (@name,@age,@x,@email) "; sqlcommand command = new sqlcommand(strsql, conn); var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray(); command.parameters.addrange(parameters); conn.open(); result = command.executenonquery(); } return result; } public t query<t>(int id) where t : bamodel { type type = typeof(t); string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]")); string sql = $"lect {columnstring} from [{type.name}] where id={id}"; t t = null;// (t)activator.createinstance(type); using (sqlconnection conn = new sqlconnection(strconn)) { sqlcommand command = new sqlcommand(sql, conn); conn.open(); sqldatareader reader = command.executereader(); list<t> list = this.readertolist<t>(reader); t = list.firstordefault(); } return t; } public list<t> queryall<t>() where t : bamodel { type type = typeof(t); string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]")); string sql = $"lect {columnstring} from [{type.name}] "; list<t> list = new list<t>(); using (sqlconnection conn = new sqlconnection(strconn)) { sqlcommand command = new sqlcommand(sql, conn); conn.open(); sqldatareader reader = command.executereader(); list = this.readertolist<t>(reader); } return list; } public int update<t>(t t) where t : bamodel { int result = 0; using (sqlconnection conn = new sqlconnection(strconn)) { type type = typeof(t); var proparray = type.getproperties().where(p => p.name != "id"); string columnstring = string.join(",", proparray.lect(p => $"[{p.getcolumnname()}]=@{p.getcolumnname()}")); var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray(); //必须参数化 否则引号? 或者值里面还有引号 string strsql = $"update [{type.name}] t {columnstring} where id={t.id}"; sqlcommand command = new sqlcommand(strsql, conn); command.parameters.addrange(parameters); conn.open(); result = command.executenonquery(); } return result; } private list<t> readertolist<t>(sqldatareader reader) where t : bamodel { type type = typeof(t); list<t> list = new list<t>(); while (reader.read())//表示有数据 开始读 { t t = (t)activator.createinstance(type); foreach (var prop in type.getproperties()) { object ovalue = reader[prop.getcolumnname()]; if (ovalue is dbnull) ovalue = null; prop.tvalue(t, ovalue);//除了guid和枚举 } list.add(t); } return list; } }}
using funapplication.dal;using funapplication.model;using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication{ 季组词 class program { static void main(string[] args) { #region myregion badal dal = new badal(); // 查询 student student = dal.query<student>(2); console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}"); console.writeline("----------------------------"); // 查询所有 list<student> list = dal.queryall<student>(); console.writeline($"集合个数:{list.count}"); console.writeline("----------------------------"); // 插入 student studentins = new student() { name = "小明", age = 20, x = 2, email = "xiaoming@qq.com" }; bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal; console.writeline($"插入执行结果:{resultins}"); console备课大师语文.writeline("----------------------------"); // 更新 student studentupd = new student() { id = 1, name = "zhangsan1234", age = 20, x = 2, email = "zhangsan1234@qq.com" }; bool resultupd = dal.update<student>(studentupd) > 0 ? true : fal; console.writeline($"更新执行结果:{resultupd}"); console.writeline("----------------------------"); // 删除 bool resultdel = dal.delete<student>(3) > 0 ? true : fal; console.writeline($"删除执行结果:{resultdel}"); #endregion console.readkey(); } }}
仔细观察上面步骤7中的代码,你会发现在每个方法中都有重复的代码,打开链接,执行sqlcommand命令,那么这些重复的代码能不能提取到一个公共的方法中进行调用呢?答案是可以的,那就是利用func委托,看下面优化后的代码:
using funapplication.attributeextend;using funapplication.idal;using funapplication.model;using system;using system.collections.generic;using system.configuration;using system.data;using system.data.sqlclient;using system.linq;using system.reflection;using system.text;using system.threading.tasks;namespace funapplication.dal{ public class funbadal : ibadal { // 数据库链接字符串 private static string strconn = configurationmanager.connectionstrings["dbconnection"].connectionstring; public int delete<t>(int id) where t : bamodel { type type = typeof(t); string sql = $"delete from {type.name} where id=@id"; func<sqlcommand, int> func = (sqlcommand command) => { sqlparameter para = new sqlparameter("id", id); command.parameters.add(para); return command.executenonquery(); }; return excutesql<int>(sql, func); } public int inrt<t>(t t) where t : bamodel { int result = 0; type type = typeof(t); var proparray = type.getproperties().where(p => p.name != "id"); string strsql = "inrt into student values (@name,@age,@x,@email) "; var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray(); func<sqlcommand, int> func = (sqlcommand command) => { command.parameters.addrange(parameters); return command.executenonquery(); }; result = excutesql<int>(strsql, func); return result; } public t query<t>(int id) where t : bamodel { type type = typeof(t); string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]")); string sql = $"lect {columnstring} from [{type.name}] where id=@id"; t t = null; datatable dt = new datatable(); func<sqlcommand, t> func = (sqlcommand command) => { sqlparameter para = new sqlparameter("@id", id); command.parameters.add(para); sqldataadapter adapter = new sqldataadapter(command); //sqldatareader reader = command.executereader(); //list<t> list = this.readertolist<t>(reader); adapter.fill(dt); list<t> list = converttolist<t>(dt); t tresult = list.firstordefault(); return tresult; }; t = excutesql<t>(sql, func); return t; } public list<t> queryall<t>() where t : bamodel { type type = typeof(t); string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]")); string sql = $"lect {columnstring} from [{type.name}] "; t t = null; func<sqlcommand, list<t>> func = (sqlcommand command) => { sqldatareader reader = command.executereader(); list<t> list = this.readertolist<t>(reader); return list; }; return excutesql<list<t>>(sql, func); } public int update<t>(t t) where t : bamodel { int result = 0; type type = typeof(t); var proparray = type.getproperties().where(p => p.name != "id"); string columnstring = string.join(",", proparray.lect(p => $"[{p.getcolumnname()}]=@{p.getcolumnname()}")); var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray(); //必须参数化 否则引号? 或者值里面还有引号 string strsql = $"update [{type.name}] t {columnstring} where id={t.id}"; func<sqlcommand, int> func = (sqlcommand command) => { command.parameters.addrange(parameters); return command.executenonquery(); }; result = excutesql<int>(strsql, func); return result; } //多个方法里面重复对数据库的访问 想通过委托解耦,去掉重复代码 private t excutesql<t>(string sql, func<sqlcommand, t> func) { using (sqlconnection conn = new sqlconnection(strconn)) { using (sqlcommand command = new sqlcommand(sql, conn)) { conn.open(); sqltransaction sqltransaction = conn.begintransaction(); try { command.transaction = sqltransaction; t tresult = func.invoke(command); sqltransaction.commit(); return tresult; } catch (exception ex) { sqltransaction.rollback(); throw; } } } } private list<t> readertolist<t>(sqldatareader reader) where t : bamodel { type type = typeof(t); list<t> list = new list<t>(); while (reader.read())//表示有数据 开始读 { t t = (t)activator.createinstance(type); foreach (var prop in type.getproperties()) { object ovalue = reader[prop.getcolumnname()]; if (ovalue is dbnull) ovalue = null; prop.tvalue(t, ovalue);//除了guid和枚举 } list.add(t); } reader.clo(); return list; } }}
using funapplication.dal;using funapplication.model;using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication{ class program { static void main(string[] args) { #region 传统实现 //badal dal = new badal(); //// 查询 //student student = dal.query<student>(2); //console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}"); //console.writeline("----------------------------"); //// 查询所有 //list<student> list = dal.queryall<student>(); //console.writeline($"集合个数:{list.count}"); //console.writeline("----------------------------"); //// 插入 //student studentins = new student() //{ // name = "小明", // age = 20, // x = 2, // email = "xiaoming@qq.com" //}; //bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal; //console.writeline($"插入执行结果:{resultins}"); //console.writeline("----------------------------"); //// 更新 //student studentupd = new student() //{ // id = 1, // name = "zhangsan1234", // age = 20, // x = 2, // email = "zhangsan1234@qq.com" //}; //bool resultupd = dal.update<student>(studentupd) > 1 ? true : fal; //console.writeline($"更新执行结果:{resultupd}"); //console.writeline("----------------------------"); //// 删除 //bool resultdel = dal.delete<student>(5) > 1 ? true : fal; //console.writeline($"删除执行结果:{resultdel}"); #endregion #region 利用委托 // 查询 funbadal dal = new funbadal(); student student = dal.query<student>(1); console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}"); console.writeline("----------------------------"); // 查询所有 list<student> list = dal.queryall<student>(); console.writeline($"集合个数:{list.count}"); console.writeline("----------------------------"); // 插入 student studentins = new student() { name = "tom", age = 19, x = 1, email = "tom@163.com" }; bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal; console.writeline($"插入执行结果:{resultins}"); console.writeline("----------------------------"); list<student> list1 = dal.queryall<student>(); console.writeline($"插入后集合个数:{list1.count}"); console.writeline("----------------------------"); // 更新 student studentupd = new student() { id = 2, name = "马六123", age = 20, x = 2, email = "maliu1234@qq.com" }; bool resultupd = dal.update<student>(studentupd) > 0 ? true : fal; console.writeline($"更新执行结果:{resultupd}"); console.writeline("----------------------------"); // 删除 bool resultdel = dal.delete<student>(8) > 0 ? true : fal; console.writeline($"删除执行结果:{resultdel}"); list<student> list2 = dal.queryall<student>(); console.writeline($"删除后集合个数:{list2.count}"); console.writeline("----------------------------"); #endregion console.readkey(); } }}
在使用sqldatareader的时候有时会报错:“已有打开的与此command相关联的datareader,必须先将它关闭”。
同时打开两个或循环多个sqldatareader会出现以上错误。因为用的是sqldatareader做数据库的数据读取,sqlconnection开启没有关闭。
一个sqlconnection只能执行一次事务,没用一次必须关闭然后再开启。上面我只用了一次没有关闭,直接开启所以会报错。解决方案有如下两种:
<?xml version="1.0" encoding="utf-8" ?><configuration> <connectionstrings> <!--<add name="dbconnection" connectionstring="rver=.;initial catalog=mydb;ur id=sa;password=123456;multipleactiveresultts=true"/>--> <!--配置文件里面添加multipleactiveresultts=true--> <add name="dbconnection" connectionstring="rver=.;initial catalog=mydb;ur id=sa;password=123456;multipleactiveresultts=true"/> </connectionstrings别日克> <startup> <supportedruntime version="v4.0" sku=".netframework,version=v4.6.1" /> </startup></configuration>
在上面是使用的sqldatareader读取数据,然后转换成list<t>,可以用datatable代替sqldatareader,这样就不会报错了,代码如下:
/// <summary>/// 将datatable转换成list/// </summary>/// <typeparam name="t"></typeparam>/// <param name="dt"></param>/// <returns></returns>private list<t> converttolist<t>(datatable dt) where t:bamodel{ type type = typeof(t); list<t> list = new list<t>(); foreach(datarow dr in dt.rows) { t t = (t)activator.createinstance(type); foreach(propertyinfo prop in type.getproperties()) { object value = dr[prop.getcolumnname()]; if(value is dbnull) { value = null; } prop.tvalue(t, value); } list.add(t); } return list;}
到此这篇关于c#内置泛型委托之func委托的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。
本文发布于:2023-04-06 03:36:10,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/ac627bd2c2c0fde7bdb6df332dbcfe54.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:C#内置泛型委托之Func委托.doc
本文 PDF 下载地址:C#内置泛型委托之Func委托.pdf
留言与评论(共有 0 条评论) |