Swift Mediator Pattern - Collection of generic protocols





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I am trying to implement a general-purpose Mediator pattern in Swift and have the following protocols and classes:



protocol Request {
}

protocol Handler {
associatedtype TRequest = Request

func handle(_ request: TRequest)
}

class RequestProcessor {

func register<THandler: Handler>(_ handler: THandler) {

}

func handle(_ request: Request) {

}

}


With the intended usage being (for example):



struct LoginRequest: Request {
let username: String
let password: String
}

struct LogoutRequest: Request {
let userId: Int
}

class LoginHandler: Handler {
func handle(_ request: LoginRequest) {
// do something
}
}

class LogoutHandler: Handler {
func handle(_ request: LogoutRequest) {
// do something
}
}

// Setup the processor and register handlers

let processor = RequestProcessor()
processor.register(LoginHandler())
processor.register(LogoutHandler())

// The processor handles any kind of Request, in this case a LoginRequest

processor.handle(LoginRequest(username: "steve", password: "..."))

// The LoginHandler's handle method will be called


However I'm not sure how to store the collection of Handler objects since it is a protocol with associated type. I am aware of type-erasure and have read several answers here as well as various articles on the subject (1, 2) but am unsure how to apply it to my situation.










share|improve this question

























  • I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

    – Kamran
    Jan 3 at 13:33


















0















I am trying to implement a general-purpose Mediator pattern in Swift and have the following protocols and classes:



protocol Request {
}

protocol Handler {
associatedtype TRequest = Request

func handle(_ request: TRequest)
}

class RequestProcessor {

func register<THandler: Handler>(_ handler: THandler) {

}

func handle(_ request: Request) {

}

}


With the intended usage being (for example):



struct LoginRequest: Request {
let username: String
let password: String
}

struct LogoutRequest: Request {
let userId: Int
}

class LoginHandler: Handler {
func handle(_ request: LoginRequest) {
// do something
}
}

class LogoutHandler: Handler {
func handle(_ request: LogoutRequest) {
// do something
}
}

// Setup the processor and register handlers

let processor = RequestProcessor()
processor.register(LoginHandler())
processor.register(LogoutHandler())

// The processor handles any kind of Request, in this case a LoginRequest

processor.handle(LoginRequest(username: "steve", password: "..."))

// The LoginHandler's handle method will be called


However I'm not sure how to store the collection of Handler objects since it is a protocol with associated type. I am aware of type-erasure and have read several answers here as well as various articles on the subject (1, 2) but am unsure how to apply it to my situation.










share|improve this question

























  • I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

    – Kamran
    Jan 3 at 13:33














0












0








0








I am trying to implement a general-purpose Mediator pattern in Swift and have the following protocols and classes:



protocol Request {
}

protocol Handler {
associatedtype TRequest = Request

func handle(_ request: TRequest)
}

class RequestProcessor {

func register<THandler: Handler>(_ handler: THandler) {

}

func handle(_ request: Request) {

}

}


With the intended usage being (for example):



struct LoginRequest: Request {
let username: String
let password: String
}

struct LogoutRequest: Request {
let userId: Int
}

class LoginHandler: Handler {
func handle(_ request: LoginRequest) {
// do something
}
}

class LogoutHandler: Handler {
func handle(_ request: LogoutRequest) {
// do something
}
}

// Setup the processor and register handlers

let processor = RequestProcessor()
processor.register(LoginHandler())
processor.register(LogoutHandler())

// The processor handles any kind of Request, in this case a LoginRequest

processor.handle(LoginRequest(username: "steve", password: "..."))

// The LoginHandler's handle method will be called


However I'm not sure how to store the collection of Handler objects since it is a protocol with associated type. I am aware of type-erasure and have read several answers here as well as various articles on the subject (1, 2) but am unsure how to apply it to my situation.










share|improve this question
















I am trying to implement a general-purpose Mediator pattern in Swift and have the following protocols and classes:



protocol Request {
}

protocol Handler {
associatedtype TRequest = Request

func handle(_ request: TRequest)
}

class RequestProcessor {

func register<THandler: Handler>(_ handler: THandler) {

}

func handle(_ request: Request) {

}

}


With the intended usage being (for example):



struct LoginRequest: Request {
let username: String
let password: String
}

struct LogoutRequest: Request {
let userId: Int
}

class LoginHandler: Handler {
func handle(_ request: LoginRequest) {
// do something
}
}

class LogoutHandler: Handler {
func handle(_ request: LogoutRequest) {
// do something
}
}

// Setup the processor and register handlers

let processor = RequestProcessor()
processor.register(LoginHandler())
processor.register(LogoutHandler())

// The processor handles any kind of Request, in this case a LoginRequest

processor.handle(LoginRequest(username: "steve", password: "..."))

// The LoginHandler's handle method will be called


However I'm not sure how to store the collection of Handler objects since it is a protocol with associated type. I am aware of type-erasure and have read several answers here as well as various articles on the subject (1, 2) but am unsure how to apply it to my situation.







swift generics design-patterns mediator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 13:29







Steve Wilford

















asked Jan 3 at 12:14









Steve WilfordSteve Wilford

7,13242861




7,13242861













  • I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

    – Kamran
    Jan 3 at 13:33



















  • I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

    – Kamran
    Jan 3 at 13:33

















I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

– Kamran
Jan 3 at 13:33





I would remove associatedType constraint from Handler so it will be protocol Handler { func handle(_ request: Request) }. Now we can declare an array of Handlers inside RequestProcessor .

– Kamran
Jan 3 at 13:33












1 Answer
1






active

oldest

votes


















1














First, the standard advice:




I am trying to implement a general-purpose Mediator pattern in Swift




Don't. Start with the actual problem you're trying to solve, and design good and necessary abstractions for that problem. Don't create generic things just to be generic. Swift will bite you over and over again. Even stdlib, which really needs super-generic things, often has to step outside of pure Swift to pull it off (using compiler special knowledge, and gyb templating). "Being generic" is not a goal in itself. You're almost certainly making this too complicated. Everyone does.



OK, that's out of the way. Second piece of advice: This is not a good use of a protocol with associated types (PAT). The point of a PAT is to add methods to types, not to be types. You never pass Collection itself or store things of that "type." You create methods that can generically work on any type that is a Collection. There is no such type as [Collection].



The fundamental problem with your approach is that there's no way to implement RequestProcessor.process() without resorting to as? casting, which breaks the point of type safety. How does processor know to call LoginHandler.process? Why that one? What if two different handlers accepted LoginRequest? What if no handler accepts that type?



What you've designed here isn't the Mediator pattern. The Mediator pattern joins together colleagues who share a single interface, so it would look like this:



class RequestProcessor<Request> {

var handlers: [(Request) -> Void] =
func register(handler: @escaping (Request) -> Void) {
handlers.append(handler)
}

func handle(request: Request) {
for handler in handlers {
handler(request)
}
}
}


And you'd have a RequestProcessor for each kind of request, not a generic "processor of every kind of request." Creating a generic one necessarily (in Swift) removes type safety, in which case you're basically creating a slightly Swiftier NotificationCenter. (It's possible to create a type-safe version of this, but it requires dependent types, which is a quite complex type feature that Swift doesn't have.)



OK, so maybe you really want this central hub and who needs type safety? Why not? You just have to say what you mean, which is that any handler has to be able to accept any request, even if it doesn't act on it. The compiler can't prove anything more specific than that because at compile time it doesn't know the types. So fine, as? it to death.



protocol Request {}

protocol Handler {
func canHandle(_ request: Request) -> Bool
func handle(_ request: Request)
}

class RequestProcessor {

private var handlers: [Handler] =

func register(_ handler: Handler) {
handlers.append(handler)
}

func handle(_ request: Request) {
for handler in handlers where handler.canHandle(request) {
handler.handle(request)
}
}
}

class LoginHandler: Handler {
func canHandle(_ request: Request) -> Bool {
return request is LoginRequest
}

func handle(_ request: Request) {
guard let loginRequest = request as? LoginRequest else { return }
// handle loginRequest
}
}


But I'd almost certainly get rid of the Mediator pattern. If the goal is to swap in and out processors for testing or whatnot, I'd just use typical dependency injection techniques. Pass the LoginHandler to whatever method creates the LoginRequest.






share|improve this answer
























  • Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

    – Steve Wilford
    Jan 3 at 16:19











  • I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

    – Rob Napier
    Jan 3 at 16:29














Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022102%2fswift-mediator-pattern-collection-of-generic-protocols%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














First, the standard advice:




I am trying to implement a general-purpose Mediator pattern in Swift




Don't. Start with the actual problem you're trying to solve, and design good and necessary abstractions for that problem. Don't create generic things just to be generic. Swift will bite you over and over again. Even stdlib, which really needs super-generic things, often has to step outside of pure Swift to pull it off (using compiler special knowledge, and gyb templating). "Being generic" is not a goal in itself. You're almost certainly making this too complicated. Everyone does.



OK, that's out of the way. Second piece of advice: This is not a good use of a protocol with associated types (PAT). The point of a PAT is to add methods to types, not to be types. You never pass Collection itself or store things of that "type." You create methods that can generically work on any type that is a Collection. There is no such type as [Collection].



The fundamental problem with your approach is that there's no way to implement RequestProcessor.process() without resorting to as? casting, which breaks the point of type safety. How does processor know to call LoginHandler.process? Why that one? What if two different handlers accepted LoginRequest? What if no handler accepts that type?



What you've designed here isn't the Mediator pattern. The Mediator pattern joins together colleagues who share a single interface, so it would look like this:



class RequestProcessor<Request> {

var handlers: [(Request) -> Void] =
func register(handler: @escaping (Request) -> Void) {
handlers.append(handler)
}

func handle(request: Request) {
for handler in handlers {
handler(request)
}
}
}


And you'd have a RequestProcessor for each kind of request, not a generic "processor of every kind of request." Creating a generic one necessarily (in Swift) removes type safety, in which case you're basically creating a slightly Swiftier NotificationCenter. (It's possible to create a type-safe version of this, but it requires dependent types, which is a quite complex type feature that Swift doesn't have.)



OK, so maybe you really want this central hub and who needs type safety? Why not? You just have to say what you mean, which is that any handler has to be able to accept any request, even if it doesn't act on it. The compiler can't prove anything more specific than that because at compile time it doesn't know the types. So fine, as? it to death.



protocol Request {}

protocol Handler {
func canHandle(_ request: Request) -> Bool
func handle(_ request: Request)
}

class RequestProcessor {

private var handlers: [Handler] =

func register(_ handler: Handler) {
handlers.append(handler)
}

func handle(_ request: Request) {
for handler in handlers where handler.canHandle(request) {
handler.handle(request)
}
}
}

class LoginHandler: Handler {
func canHandle(_ request: Request) -> Bool {
return request is LoginRequest
}

func handle(_ request: Request) {
guard let loginRequest = request as? LoginRequest else { return }
// handle loginRequest
}
}


But I'd almost certainly get rid of the Mediator pattern. If the goal is to swap in and out processors for testing or whatnot, I'd just use typical dependency injection techniques. Pass the LoginHandler to whatever method creates the LoginRequest.






share|improve this answer
























  • Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

    – Steve Wilford
    Jan 3 at 16:19











  • I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

    – Rob Napier
    Jan 3 at 16:29


















1














First, the standard advice:




I am trying to implement a general-purpose Mediator pattern in Swift




Don't. Start with the actual problem you're trying to solve, and design good and necessary abstractions for that problem. Don't create generic things just to be generic. Swift will bite you over and over again. Even stdlib, which really needs super-generic things, often has to step outside of pure Swift to pull it off (using compiler special knowledge, and gyb templating). "Being generic" is not a goal in itself. You're almost certainly making this too complicated. Everyone does.



OK, that's out of the way. Second piece of advice: This is not a good use of a protocol with associated types (PAT). The point of a PAT is to add methods to types, not to be types. You never pass Collection itself or store things of that "type." You create methods that can generically work on any type that is a Collection. There is no such type as [Collection].



The fundamental problem with your approach is that there's no way to implement RequestProcessor.process() without resorting to as? casting, which breaks the point of type safety. How does processor know to call LoginHandler.process? Why that one? What if two different handlers accepted LoginRequest? What if no handler accepts that type?



What you've designed here isn't the Mediator pattern. The Mediator pattern joins together colleagues who share a single interface, so it would look like this:



class RequestProcessor<Request> {

var handlers: [(Request) -> Void] =
func register(handler: @escaping (Request) -> Void) {
handlers.append(handler)
}

func handle(request: Request) {
for handler in handlers {
handler(request)
}
}
}


And you'd have a RequestProcessor for each kind of request, not a generic "processor of every kind of request." Creating a generic one necessarily (in Swift) removes type safety, in which case you're basically creating a slightly Swiftier NotificationCenter. (It's possible to create a type-safe version of this, but it requires dependent types, which is a quite complex type feature that Swift doesn't have.)



OK, so maybe you really want this central hub and who needs type safety? Why not? You just have to say what you mean, which is that any handler has to be able to accept any request, even if it doesn't act on it. The compiler can't prove anything more specific than that because at compile time it doesn't know the types. So fine, as? it to death.



protocol Request {}

protocol Handler {
func canHandle(_ request: Request) -> Bool
func handle(_ request: Request)
}

class RequestProcessor {

private var handlers: [Handler] =

func register(_ handler: Handler) {
handlers.append(handler)
}

func handle(_ request: Request) {
for handler in handlers where handler.canHandle(request) {
handler.handle(request)
}
}
}

class LoginHandler: Handler {
func canHandle(_ request: Request) -> Bool {
return request is LoginRequest
}

func handle(_ request: Request) {
guard let loginRequest = request as? LoginRequest else { return }
// handle loginRequest
}
}


But I'd almost certainly get rid of the Mediator pattern. If the goal is to swap in and out processors for testing or whatnot, I'd just use typical dependency injection techniques. Pass the LoginHandler to whatever method creates the LoginRequest.






share|improve this answer
























  • Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

    – Steve Wilford
    Jan 3 at 16:19











  • I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

    – Rob Napier
    Jan 3 at 16:29
















1












1








1







First, the standard advice:




I am trying to implement a general-purpose Mediator pattern in Swift




Don't. Start with the actual problem you're trying to solve, and design good and necessary abstractions for that problem. Don't create generic things just to be generic. Swift will bite you over and over again. Even stdlib, which really needs super-generic things, often has to step outside of pure Swift to pull it off (using compiler special knowledge, and gyb templating). "Being generic" is not a goal in itself. You're almost certainly making this too complicated. Everyone does.



OK, that's out of the way. Second piece of advice: This is not a good use of a protocol with associated types (PAT). The point of a PAT is to add methods to types, not to be types. You never pass Collection itself or store things of that "type." You create methods that can generically work on any type that is a Collection. There is no such type as [Collection].



The fundamental problem with your approach is that there's no way to implement RequestProcessor.process() without resorting to as? casting, which breaks the point of type safety. How does processor know to call LoginHandler.process? Why that one? What if two different handlers accepted LoginRequest? What if no handler accepts that type?



What you've designed here isn't the Mediator pattern. The Mediator pattern joins together colleagues who share a single interface, so it would look like this:



class RequestProcessor<Request> {

var handlers: [(Request) -> Void] =
func register(handler: @escaping (Request) -> Void) {
handlers.append(handler)
}

func handle(request: Request) {
for handler in handlers {
handler(request)
}
}
}


And you'd have a RequestProcessor for each kind of request, not a generic "processor of every kind of request." Creating a generic one necessarily (in Swift) removes type safety, in which case you're basically creating a slightly Swiftier NotificationCenter. (It's possible to create a type-safe version of this, but it requires dependent types, which is a quite complex type feature that Swift doesn't have.)



OK, so maybe you really want this central hub and who needs type safety? Why not? You just have to say what you mean, which is that any handler has to be able to accept any request, even if it doesn't act on it. The compiler can't prove anything more specific than that because at compile time it doesn't know the types. So fine, as? it to death.



protocol Request {}

protocol Handler {
func canHandle(_ request: Request) -> Bool
func handle(_ request: Request)
}

class RequestProcessor {

private var handlers: [Handler] =

func register(_ handler: Handler) {
handlers.append(handler)
}

func handle(_ request: Request) {
for handler in handlers where handler.canHandle(request) {
handler.handle(request)
}
}
}

class LoginHandler: Handler {
func canHandle(_ request: Request) -> Bool {
return request is LoginRequest
}

func handle(_ request: Request) {
guard let loginRequest = request as? LoginRequest else { return }
// handle loginRequest
}
}


But I'd almost certainly get rid of the Mediator pattern. If the goal is to swap in and out processors for testing or whatnot, I'd just use typical dependency injection techniques. Pass the LoginHandler to whatever method creates the LoginRequest.






share|improve this answer













First, the standard advice:




I am trying to implement a general-purpose Mediator pattern in Swift




Don't. Start with the actual problem you're trying to solve, and design good and necessary abstractions for that problem. Don't create generic things just to be generic. Swift will bite you over and over again. Even stdlib, which really needs super-generic things, often has to step outside of pure Swift to pull it off (using compiler special knowledge, and gyb templating). "Being generic" is not a goal in itself. You're almost certainly making this too complicated. Everyone does.



OK, that's out of the way. Second piece of advice: This is not a good use of a protocol with associated types (PAT). The point of a PAT is to add methods to types, not to be types. You never pass Collection itself or store things of that "type." You create methods that can generically work on any type that is a Collection. There is no such type as [Collection].



The fundamental problem with your approach is that there's no way to implement RequestProcessor.process() without resorting to as? casting, which breaks the point of type safety. How does processor know to call LoginHandler.process? Why that one? What if two different handlers accepted LoginRequest? What if no handler accepts that type?



What you've designed here isn't the Mediator pattern. The Mediator pattern joins together colleagues who share a single interface, so it would look like this:



class RequestProcessor<Request> {

var handlers: [(Request) -> Void] =
func register(handler: @escaping (Request) -> Void) {
handlers.append(handler)
}

func handle(request: Request) {
for handler in handlers {
handler(request)
}
}
}


And you'd have a RequestProcessor for each kind of request, not a generic "processor of every kind of request." Creating a generic one necessarily (in Swift) removes type safety, in which case you're basically creating a slightly Swiftier NotificationCenter. (It's possible to create a type-safe version of this, but it requires dependent types, which is a quite complex type feature that Swift doesn't have.)



OK, so maybe you really want this central hub and who needs type safety? Why not? You just have to say what you mean, which is that any handler has to be able to accept any request, even if it doesn't act on it. The compiler can't prove anything more specific than that because at compile time it doesn't know the types. So fine, as? it to death.



protocol Request {}

protocol Handler {
func canHandle(_ request: Request) -> Bool
func handle(_ request: Request)
}

class RequestProcessor {

private var handlers: [Handler] =

func register(_ handler: Handler) {
handlers.append(handler)
}

func handle(_ request: Request) {
for handler in handlers where handler.canHandle(request) {
handler.handle(request)
}
}
}

class LoginHandler: Handler {
func canHandle(_ request: Request) -> Bool {
return request is LoginRequest
}

func handle(_ request: Request) {
guard let loginRequest = request as? LoginRequest else { return }
// handle loginRequest
}
}


But I'd almost certainly get rid of the Mediator pattern. If the goal is to swap in and out processors for testing or whatnot, I'd just use typical dependency injection techniques. Pass the LoginHandler to whatever method creates the LoginRequest.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 3 at 14:30









Rob NapierRob Napier

207k28306434




207k28306434













  • Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

    – Steve Wilford
    Jan 3 at 16:19











  • I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

    – Rob Napier
    Jan 3 at 16:29





















  • Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

    – Steve Wilford
    Jan 3 at 16:19











  • I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

    – Rob Napier
    Jan 3 at 16:29



















Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

– Steve Wilford
Jan 3 at 16:19





Thanks for this detailed answer, I appreciate the push away from potentially going down completely the wrong path. The reasoning is purely academic, I'm not trying to solve a specific problem, rather trying to port the .NET Mediatr library to Swift, with a bit of learning thrown in for good measure. I think I can live with a variation of the last example you gave but pulling the guard / as? clauses into the processor and have the handlers be explicit about the request they handle, probably with a base class rather than a protocol.

– Steve Wilford
Jan 3 at 16:19













I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

– Rob Napier
Jan 3 at 16:29







I think you'll find you can't move the as? clause to the caller, because any Handler must implement some handle method that accepts the same type. You can't call a method using a type that isn't known at compile-time. While an interesting problem, I would recommend against porting a framework that solves a C# problem (likely driven by the pre-3.0 lack of first-class functions), and instead reimagine the underlying problem using Swift tools (particularly first-class functions), and focusing on Swift problems. Most "patterns" are not nearly as universal as they claim to be.

– Rob Napier
Jan 3 at 16:29






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022102%2fswift-mediator-pattern-collection-of-generic-protocols%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

How to fix TextFormField cause rebuild widget in Flutter