I have heard about the name of generics in .NET 2.0, but it has not been used in actual development.
I recently experienced it during the development of the Blog Park website program.
Application scenarios:
Read the corresponding mail settings in the configuration file through deserialization.
Configuration file example:
<BlogConfigurationSettings>
<MailSettings>
<MailSetting Name="ApproveEmail" SmtpServer="smtp.126.com" EmailFrom="" UserName="" PassWord=""></MailSetting>
<MailSetting Name="ContactEmail" SmtpServer="smtp.163.com" EmailFrom="" UserName="" PassWord=""></MailSetting>
</MailSettings>
</BlogConfigurationSettings>
Function description:
Through the configuration file, the attribute MailSettings of the BlogConfigurationSettings instance is obtained through deserialization, and then the corresponding MailSetting is obtained according to the keyword, for example: the MailSetting named ApproveEmail.
Definition of MailSetting:
MailSetting
[Serializable]
public class MailSetting
{
private string _name;
[XmlAttribute("Name")]
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _smtpServer;
[XmlAttribute("SmtpServer")]
public string SmtpServer
{
get { return _smtpServer; }
set { _smtpServer = value; }
}
private string _mailFrom;
[XmlAttribute("MailFrom")]
public string MailFrom
{
get { return _mailFrom; }
set { _mailFrom = value; }
}
private string _username;
[XmlAttribute("UserName")]
public string UserName
{
get { return _username; }
set { _username = value; }
}
private string _password;
[XmlAttribute("Password")]
public string Password
{
get { return _password; }
set { _password = value; }
}
public string Key
{
get { return this.Name; }
}
}
If we don't use generics, we can implement it through arrays or collection classes.
For arrays, we need to define this in BlogConfigurationSettings:
private MailSetting [] __mailSettings;
[XmlArray("MailSettings")]
public MailSetting [] MailSettings
{
get { return this._mailSettings; }
set { this._mailSettings = value; }
}We also need to write a method to enumerate the array elements and return the corresponding MailSetting based on the keyword.
For collection classes, you need to define this in BlogConfigurationSettings:
private MailSettingCollection _mailSettings;
[XmlArray("MailSettings")]
public MailSettingColletion MailSettings
{
get { return this._mailSettings; }
set { this._mailSettings = value; }
}We need to write a MailSettingCollection class, and implement a method in MailSettingCollection to find the corresponding MailSetting based on keywords.
For generics, we only need to define the following in BlogConfigurationSettings:
private List<MailSetting> _mailSettings;
[XmlArray("MailSettings")]
public List<MailSetting> MailSettings
{
get { return _mailSettings; }
set { _mailSettings = value;}
}
Then just the following line of code can get the corresponding MailSetting based on the keyword:
BlogConfigurationSettings.MailSettings.Find(delegate(MailSetting mailSetting) { return mailSetting.Key == "ApproveEmail"; })
The parameter type of the Find method is Predicate<T>, and its definition is:
public delegate bool Predicate<T>(T obj)
That is, a delegate type whose parameters are generic and whose return value is bool.
The function of Find is to enumerate the elements in List<T> and call the delegate with each element as a parameter of the delegate. The actual delegate method is passed through the Find parameter. When the called delegate returns true, the current element is returned.
You can also write the code in the Find parameter above as a separate method, and then use the method name as the parameter of Find.
BlogConfigurationSettings.MailSettings.Find(IsMe);
public bool IsMe(MailSetting mailSetting)
{
return mailSetting.Key == "ApproveEmail";
}
You will immediately feel uncomfortable with such code. Why not write a method for each keyword? You think it should be written like this:
public bool IsMe(MailSetting mailSetting, string key)
{
return mailSetting.Key == key;
}
Of course it's good to write it this way, but Find disagrees. Its parameters are only allowed to be methods with one parameter.
So how to solve this problem?
A solution I thought of was to write a MailSettingPredicate class:
public class MailSettingPredicate
{
private string key;
public string Key
{
get { return key; }
set { key = value; }
}
public bool IsMe(MailSetting mailSetting)
{
return mailSetting.Key == this.key;
}
}
Before calling IsMe, first set the value of MailSettingManager.Key. The code is as follows:
MailSettingPredicate predicate= new MailSettingPredicate();
predicate.Key = "ApproveEmail";
Config.Settings.MailSettings.Find(predicate.IsMe);
predicate.Key = "ContactEmail";
Config.Settings.MailSettings.Find(predicate.IsMe);
I have just used .NET 2.0 generics in actual development. I write this article to deepen my understanding. I also hope to provide some reference for friends who are not familiar with .NET 2.0 generics. You are welcome to point out any shortcomings.