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方法,該方法邏輯很簡單,就是根據綁定的屬性層級(.分隔)層層遍歷獲取屬性的值,直到遍歷完或為空時停止,最後得到的結果即是綁定的屬性的值。最終實現的效果如下圖示: