近期开发项目中用到的编码小技巧汇总说明

2017-01-14 08:42:52来源:cnblogs.com作者:梦在旅途人点击

第七城市

1.默认EF生成的连接字符串比较的长和怪异,若想使用普通的连接字符串来连接EF,则可以通过创建分部类,并重写一个构造函数,在构造函数中通过动态拼接EntityConnectionString得到EF所需的连接字符串,具代实现代码如下:

    public partial class DataEntities    {        private static ConcurrentDictionary<string, string> entityConnStrings = new ConcurrentDictionary<string, string>();        public DataEntities(string connName)            : base(BuildEntityConnectionString(connName))        {        }        private static string BuildEntityConnectionString(string connName)        {            if (!entityConnStrings.ContainsKey(connName))            {                var connStrSetting = System.Configuration.ConfigurationManager.ConnectionStrings[connName];                EntityConnectionStringBuilder entityConnStrBuilder = new EntityConnectionStringBuilder();                entityConnStrBuilder.Provider = connStrSetting.ProviderName;                entityConnStrBuilder.ProviderConnectionString = EncryptUtility.DesDecrypt("XXXXX", connStrSetting.ConnectionString);                entityConnStrBuilder.Metadata = "res://*/Data.csdl|res://*/Data.ssdl|res://*/Data.msl";                string entityConnString = entityConnStrBuilder.ToString();                entityConnStrings.AddOrUpdate(connName, entityConnString, (key, value) => entityConnString);            }            return entityConnStrings[connName];        }    }

注意上面的类是一个分部类:partial,同时BuildEntityConnectionString方法是一个静态方法,在BuildEntityConnectionString方法中ProviderConnectionString = EncryptUtility.DesDecrypt("XXXXX", connStrSetting.ConnectionString);是关键,我这里是对config中的连接字符串 也都进行了加密,故此处我需要解密,若无这个需求可以直接:ProviderConnectionString =connStrSetting.ConnectionString即可。后续实例化EF上下文对象时,请使用:DataEntities(string connName)这个构造涵数即可,DataEntities是具体的EF上下文对象,大家的EF上下文类名均可能不相同。

2.支持一个通用对象的XML序列化(即:一个类中有可变类型属性成员,需要不同的序列结果及生成不同的序列元素名称),具体实现代码如下:

一个需要被序列化成XML的类:其中要求生成的XML元素detail必需有子元素,且子元素名称及子元素内部属性根据类型的不同而不同(即:detail元素下的子元素是可变的)

    [XmlRootAttribute("master")]    public class DemoMaster<T> where T : class    {        [XmlElement("attr")]        public string DemoAttr { get; set; }        [XmlElement("detail")]        public DemoDetail<T> DemoDetail { get; set; } //关键点在这里,该属性元素为:detail,但其子元素根据T不同而不同    }    public class DemoDetail<T> : IXmlSerializable where T : class    {        public T body { get; set; }        public System.Xml.Schema.XmlSchema GetSchema()        {            return null;        }        public void ReadXml(System.Xml.XmlReader reader)        {            string bodyStr = reader.ReadInnerXml();            this.body = XmlHelper.XmlDeserialize<T>(bodyStr, Encoding.UTF8);        }        public void WriteXml(System.Xml.XmlWriter writer)        {            writer.WriteRaw(XmlHelper.XmlSerialize(this.body, Encoding.UTF8, true));        }    }    [XmlTypeAttribute("list-a", AnonymousType = false)]    public class DemoDetailA    {        public string Apro1 { get; set; }        public string Apro2 { get; set; }        public string Apro3 { get; set; }    }    [XmlTypeAttribute("list-b", AnonymousType = false)]    public class DemoDetailB    {        public string Bpro1 { get; set; }        public string Bpro2 { get; set; }        public string Bpro3 { get; set; }    }    [XmlTypeAttribute("list-c", AnonymousType = false)]    public class DemoDetailC    {        public string Cpro1 { get; set; }        public string Cpro2 { get; set; }        public string Cpro3 { get; set; }    }

注意上面代码中,需要关注:DemoDetail属性及DemoDetail<T>类,DemoDetail属性仅是为了生成detail元素节点,而子节点则由DemoDetail<T>类来进行生成,DemoDetail<T>是实现了IXmlSerializable接口,在XML序列化时,DemoDetail<T>类仅将body属性对应的T类型实例内容进行序列化(WriteRaw),而反序列化时,则先反序列化body属性对应的T类型实例,然后赋值给body属性,这也是巧妙之处,DemoDetail<T>类本身并没有真正参与到序列化中,故序列化的字符串也看不到DemoDetail<T>类相关的元素,DemoDetail<T>类仅仅是一个XML序列化格式生成的中介。序列化的XML结果如下:

序列化代码:

            var demo1 = new DemoMaster<DemoDetailA>()            {                DemoAttr = "demo1",                DemoDetail = new DemoDetail<DemoDetailA>() { body = new DemoDetailA() { Apro1 = "demoA1", Apro2 = "demoA2", Apro3 = "demoA3" } }            };            var demo2 = new DemoMaster<DemoDetailB>()            {                DemoAttr = "demo2",                DemoDetail = new DemoDetail<DemoDetailB>() { body = new DemoDetailB() { Bpro1 = "demoB1", Bpro2 = "demoB2", Bpro3 = "demoB3" } }            };            var demo3 = new DemoMaster<DemoDetailC>()            {                DemoAttr = "demo3",                DemoDetail = new DemoDetail<DemoDetailC>() { body = new DemoDetailC() { Cpro1 = "demoC1", Cpro2 = "demoC2", Cpro3 = "demoC3" } }            };            textBox1.Text = XmlHelper.XmlSerialize(demo1, Encoding.UTF8);            textBox1.Text += "/r/n" + XmlHelper.XmlSerialize(demo2, Encoding.UTF8);            textBox1.Text += "/r/n" + XmlHelper.XmlSerialize(demo3, Encoding.UTF8);

序列化的XML:

<?xml version="1.0" encoding="utf-8"?><master>    <attr>demo1</attr>    <detail><list-a>    <Apro1>demoA1</Apro1>    <Apro2>demoA2</Apro2>    <Apro3>demoA3</Apro3></list-a></detail></master><?xml version="1.0" encoding="utf-8"?><master>    <attr>demo2</attr>    <detail><list-b>    <Bpro1>demoB1</Bpro1>    <Bpro2>demoB2</Bpro2>    <Bpro3>demoB3</Bpro3></list-b></detail></master><?xml version="1.0" encoding="utf-8"?><master>    <attr>demo3</attr>    <detail><list-c>    <Cpro1>demoC1</Cpro1>    <Cpro2>demoC2</Cpro2>    <Cpro3>demoC3</Cpro3></list-c></detail></master>

3.winform DataGridView 实现指定列采取密码框模式显示与编辑,以及列绑定到复合属性(即:绑定到多层次属性),具体实现代码如下:

            dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);            dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);        public string EvaluateValue(object obj, string property)        {            string retValue = string.Empty;            string[] names = property.Split('.');            for (int i = 0; i < names.Count(); i++)            {                try                {                    var prop = obj.GetType().GetProperty(names[i]);                    var result = prop.GetValue(obj, null);                    if (result != null)                    {                        obj = result;                        retValue = result.ToString();                    }                    else                    {                        break;                    }                }                catch (Exception)                {                    throw;                }            }            return retValue;        }        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)        {            if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains("."))            {                e.Value = EvaluateValue(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName);            }            if (dataGridView1.Columns[e.ColumnIndex].Name == "KeyCode")            {                if (e.Value != null && e.Value.ToString().Length > 0)                {                    e.Value = new string('*', e.Value.ToString().Length);                }            }        }        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)        {            int i = this.dataGridView1.CurrentCell.ColumnIndex;            bool usePassword = false;            if (dataGridView1.Columns[i].Name == "KeyCode")            {                usePassword = true;            }            TextBox txt = e.Control as TextBox;            if (txt != null)            {                txt.UseSystemPasswordChar = usePassword;            }        }//示例:绑定的源数据类定义    public class DemoBindClass    {        public string Attr { get; set; }        public string KeyCode { get; set; }        public DemoDetailA Detail { get; set; }    }    public class DemoDetailA    {        public string Apro1 { get; set; }        public string Apro2 { get; set; }        public string Apro3 { get; set; }        public DemoDetailB DetailChild { get; set; }    }    public class DemoDetailB    {        public string Bpro1 { get; set; }        public string Bpro2 { get; set; }        public string Bpro3 { get; set; }    }

绑定到数据源:

            var demo = new[] {                new DemoBindClass()                    {                        Attr = "demo",                        KeyCode="a123456789b",                        Detail = new DemoDetailA()                        {                            Apro1 = "demoA1",                            Apro2 = "demoA2",                            Apro3 = "demoA3",                            DetailChild = new DemoDetailB()                            {                                Bpro1 = "demoB1",                                Bpro2 = "demoB2",                                Bpro3 = "demoB3"                            }                        }                    }            };            dataGridView1.AutoGenerateColumns = false;            dataGridView1.DataSource = demo;

实现指定列采取密码框模式显示与编辑,以及列绑定到复合属性均需要订阅DataGridView的CellFormatting及EditingControlShowing事件,并在其中写转换当前Cell的Value,实现列绑定到复合属性,关键点在:EvaluateValue方法,该方法逻辑很简单,就是根据绑定的属性层级(.分隔)层层遍历获取属性的值,直到遍历完或为空时停止,最后得到的结果即是绑定的属性的值。最终实现的效果如下图示:

  

 

第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台