1117 Дополняю ответ Димы. Поскольку вы всегда хотите делегировать логику isValid
соответствующей Payment
. Я представлю вам два способа не переопределять метод в каждом подклассе.
Один метод, использующий F-ограниченный полиморфизм , который потребует достаточно стандартного кода для каждого подкласса, и он не является полностью типобезопасным - таким образом, может не стоить работы.
И второе, используя классов типов , которые будут более типов безопасными и потребуют меньше шаблонов для каждой новой карты.
Для более подробного обсуждения F-ограниченных и классов типов , прочитайте эту статью.
sealed trait CreditCardPayment[CC <: CreditCard[CC]] {
def isValid(creditCard: CC): Boolean
def checkCVV(creditCard: CC): Boolean
}
object VisaCreditCardPayment extends CreditCardPayment[VisaCreditCard] {
private final val validCreditCards: List[VisaCreditCard] = ???
override def isValid(creditCard: VisaCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: VisaCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
object MasterCreditCardPayment extends CreditCardPayment[MasterCreditCard] {
private final val validCreditCards: List[MasterCreditCard] = ???
override def isValid(creditCard: MasterCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: MasterCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
sealed trait CreditCard[CC <: CreditCard[CC]] { self: CC =>
def paymentMethod: CreditCardPayment[CC]
def cvv: String
final def isValid: Boolean =
paymentMethod.isValid(this)
}
final class VisaCreditCard (override val cvv: String) extends CreditCard[VisaCreditCard] {
override final val paymentMethod: CreditCardPayment[VisaCreditCard] = VisaCreditCardPayment
}
final class MasterCreditCard (override val cvv: String) extends CreditCard[MasterCreditCard] {
override final val paymentMethod: CreditCardPayment[MasterCreditCard] = MasterCreditCardPayment
}
sealed trait CreditCardPayment[CC <: CreditCard] {
def isValid(creditCard: CC): Boolean
def checkCVV(creditCard: CC): Boolean
}
sealed trait CreditCard {
def cvv: String
}
// Provides the 'isValid' & 'checkCVV' extension methods to any CredictCard.
implicit class CreditCardOps[CC <: CreditCard](val self: CC) extends AnyVal {
def isValid(implicit payment: CreditCardPayment[CC]): Boolean =
payment.isValid(self)
def checkCVV(implicit payment: CreditCardPayment[CC]): Boolean =
payment.checkCVV(self)
}
final class VisaCreditCard (override val cvv: String) extends CreditCard
object VisaCreditCard {
final implicit val VisaCreditCardPayment: CreditCardPayment[VisaCreditCard] = new CreditCardPayment[VisaCreditCard] {
final val validCreditCards: List[VisaCreditCard] = ???
override def isValid(creditCard: VisaCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: VisaCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
}
final class MasterCreditCard (override val cvv: String) extends CreditCard
object MasterCreditCard {
final implicit val MasterCreditCardPayment: CreditCardPayment[MasterCreditCard] = new CreditCardPayment[MasterCreditCard] {
final val validCreditCards: List[MasterCreditCard] = ???
override def isValid(creditCard: MasterCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: MasterCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
}
Используя подход класса типов , вы также можете определить метод isValid
для CreditCards
вместо этого.
(Таким образом, вам не нужно определять и импортировать CreditCardOps
класс неявных / значений) .
def isValid[CC <: CreditCard](cc: CC)(implicit payment: CreditCardPayment[CC]): Boolean =
payment.isValid(cc)
Я перекомментарий chilkat . У них есть довольно стабильные компоненты, и можно получить их почтовый компонент для столь же дешевого как 99$ для единственного разработчика. Лично, я думаю, идя с целым пакетом компонентов, более выгодные условия, поскольку это - только 289$ и идет со многими полезными компонентами. Я не аффилирован с ними всегда, хотя я, вероятно, кажусь, что я.
Как насчет WCF? Это свободно.
, Если у Вас есть Exchange Server: http://msdn.microsoft.com/en-us/library/bb397812.aspx
пример для pop3: http://bartdesmet.net/blogs/bart/archive/2006/09/13/4417.aspx
Lumisoft является открытым исходным кодом и включает IMAP и клиенты POP (среди другого материала). Я использовал их в течение многих лет без проблем.
Я рекомендовал бы AdvancedIntellect. Существуют компоненты для POP3 и IMAP (ASPNetPOP3 и ASPNetIMAP). Хорошее качество и очень быстро реагирующая поддержка - я не забываю получать ответы на свои вопросы в выходные.
Я использую свободный и SharpMimeTools с открытым исходным кодом в своем приложении, BugTracker.NET. Это было очень надежно:
http://anmar.eu.org/projects/sharpmimetools/
Видит файлы POP3Client.cs, POP3Main.cs и insert_bug.aspx
Если вы используете реализацию POP3 с открытым исходным кодом или что-то в свободном доступе, у вас будет доступ для изменения кода и расширения его в нужном направлении. Быстрый поиск в Google привел к получению этого кода POP3 C # из Code Project для извлечения сообщений.
Есть что-то вдохновляющее в прокрутке вашего собственного или, по крайней мере, его расширении.
Вы можете проверить наш компонент Rebex Mail . Он включает протоколы IMAP , SMTP , POP3 и парсер S / MIME .
POP3
не имеет концепции «непрочитанных» сообщений или поиска сообщений, соответствующих определенным критериям. POP3
просто возвращает все сообщения в вашем почтовом ящике.
Используя IMAP
, вы можете указать серверу IMAP отправлять вам только непрочитанные сообщения, сообщения, пришедшие с указанного времени, сообщения от определенного пользователя и т. Д. Вам не нужно загружать все это на клиент и сделайте фильтрацию там.
Следующий код показывает, как загружать непрочитанные сообщения с сервера Imap
с помощью класса Rebex.Net.Imap
.
// create client, connect and log in
Imap client = new Imap();
client.Connect("imap.example.org");
client.Login("username", "password");
// select folder
client.SelectFolder("Inbox");
// get message list - envelope headers
ImapMessageCollection messages = client.Search
(
ImapSearchParameter.HasFlagsNoneOf(ImapMessageFlags.Seen)
);
// display info about each message
Console.WriteLine("UID | From | To | Subject");
foreach (ImapMessageInfo message in messages)
{
Console.WriteLine(
"{0} | {1} | {2} | {3}",
message.UniqueId,
message.From,
message.To,
message.Subject);
}
// disconnect
client.Disconnect();
Далее следует пример объединения нескольких критериев поиска. Это вернет сообщения за последний год размером более 100 КБ.
ImapMessageCollection messages = client.Search
(
ImapSearchParameter.Arrived(DateTime.Now.AddYears(-1), DateTime.Now),
ImapSearchParameter.Size(1024 * 100, Int32.MaxValue)
);
Вы можете скачать пробную версию по ссылке rebex.net/secure-mail.net/download.aspx
C#Mail стоит $0, но также имеет лицензию GNU GPL, так что убедитесь, что это нормально.