#c# #generics #delegates
#c# #универсальные методы #делегаты
Вопрос:
У меня есть интерфейс с кучей методов с разными сигнатурами (контекст здесь — интерфейс обратного вызова WCF). На моем сервере есть список клиентов. В ответ на события я хочу вызывать метод интерфейса на каждом клиенте. Вокруг этого вызова есть куча кода котельной панели (проверьте, работает ли клиент, должен ли этот клиент быть включен в список для обратного вызова, попробуйте перехватить, удалите клиент, если операция завершится неудачей и т.д.). Каков наилучший способ извлечь этот код базовой панели в общий CallBackClients (SomeKindOfGenericDeligate method_to_call), где method_to_call является одним из методов интерфейса.
ICallback {
void Fish(string my_string);
void SuperFish(int my_int, double my_double);
... etc ...
}
CallBackClients( -- ?? generic delegate ?? -- ) {
foreach (IClientCallback client in client_list) {
// The boiler plate code:
if (((ICommunicationObject)client.callback).State == CommunicationState.Opened) {
try {
Do method call based on delagate / lamda code passed in - how ??
}
catch (Exception e) {
Remove_client(client, method.ToString(), e);
}
}
else
Remove_client(client, method.ToString());
}
}
}
Псевдокод для вызывающего:
void EventHandler_A() {
// Call Fish method on all clients:
CallBackClients(Fish("hello"));
}
void EventHandler_B() {
// Call SuperFish method on all clients:
CallBackClients(SuperFish(10, 5.3);
}
Ответ №1:
Вы можете инкапсулировать метод для последующего вызова в любой заданный IClientCallBack
в Action<IClientCallBack>
:
CallBackClients(Action<IClientCallBack> actionOnDelegates) {
foreach (IClientCallback client in client_list) {
// The boiler plate code:
if (((ICommunicationObject)client.callback).State == CommunicationState.Opened) {
try {
actionOnDelegates(client);
}
catch (Exception e) {
Remove_client(client, method.ToString(), e);
}
}
else
Remove_client(client, method.ToString());
}
}
}
затем это будет вызываться следующим образом; они создают анонимный метод для вызова метода на указанном client
:
void EventHandler_A() {
// Call Fish method on all clients:
CallBackClients(client => client.Fish("hello"));
}
void EventHandler_B() {
// Call SuperFish method on all clients:
CallBackClients(client => client.SuperFish(10, 5.3);
}
Комментарии:
1. Это не сработало бы, если бы методы обратного вызова что-то вернули. Но, вероятно, здесь проблема не в этом.
2. В таком случае
CallBackClients
метод может быть сделан универсальным вT
, а делегат может быть изменен наFunc<IClientCallback, T>
с передачей возвращаемого значения соответствующим образом.3. Все обратные вызовы являются недействительными / односторонними — так что все в порядке.
4. @thecoop Отличный ответ — спасибо. Я знал, что решение существует, но я не мог полностью собрать его воедино.