I want to store delegates(Action) with one generic parameter in a Dictionary and I would like to avoid any Code Smell
regarding to down/up-casting if that is possible at all.
Basically I am implementing some kind of a Request/Response Callback manager where the user requests something from a
REST API and provides me a callback with the correct Response object. In a nutshell the method the user calls looks like that:
void GetUser(int id, Action<GetUserResponse> callback);
I then, sent out the request and save the callback into my "Callback Manager". When the response from the server
comes in (mostly json) I parse it into a GetUserResponse object and fire the callback. However there are many different
Requests which have different response objects and the Callback Manager has to prioritize them (and also some other stuff)
Instead of having a Dictionary for every single request which stores the callbacks of that request, I would like to
have a single Dictionary which stores all of the callbacks (and a unique id).
Basically something like this: (which obviously does not work like that)
Dictionary<GUID,Action<T>> AllCallbacks;
Is that possible without having to cast anything on the "user side"?
Have a look at Dictionary of Action<T> Delegates.
Should give you some guidance of options available to you. I don't think there is a simple and elegant solution out of the box.
You could use Dictionary<GUID,Action<dynamic>> AllCallbacks; but then you would need to type check and cast accordingly.
Related
I have the following delegate
System.Action<SomeMessage> TheDelegate;
Which has a couple subscribers, however as the message gets passed through all the subscribers, each subscriber will do something to it and that change persists and gets passed to the next subscriber, which is something that I don't want.
Is there a way that I can use the original message as the parameter for all subscribers?
Edit:
SomeMessage is a class, thus it gets passed by reference through the subscribers
To name two possibilities:
Clone the message each time it is passed to a subscriber. How is the message structured, is it cheap to clone? Maybe you could even pass it as struct? Cloning could be done by implementing ICloneable, clone on a per-property basis, which can be automated by a framework, e.g, Automapper (http://automapper.org) or, if you mess around with some JSON Lib like JSON.NET, you could do something like var clone = FromJson(ToJson(original)). This is surely not a fast approach but an easy one that works well with deep objects.
Another way would be making the message itself immutable and let each subscriber pass change requests to some kind of collector, e.g.
like this:
interface ICommandSequence
{
void AddCommand(ICommand);
}
and the Action becomes
System.Action<ImmutableMessage, ICommandSequence>
Each subscriber could now pass command instances to the ICommandSequence instance. And after all subscribers have been called, you could execute the command sequence, and apply changes to message objects. How the commands look depends on the way your messages and message processing looks.
If your application cares about a design that is strongly focused on the business domain, you could build commands that represent real-world business events, as it is done in CQRS, for example.
We have a system built using WCF and we are in the process of converting it to use Mass Transit and RabbitMQ.
Because it is/was a WCF service its quite RESTful in the way it operates, there are no states or sessions.
With this in mind, moving to Mass Tranist thus requires a huge amount of boiler plate code. For example we have possibly 100 WCF calls. For each one I would have to implement a separate Request/Response pair that, aside from the name, would be no different to each other. Apparently I cannot even use inheritance to abstract away the CorrelatedBy<Guid> syntax.
Is there any way I can reduce the amount of boilerplate code required to do this?
My current MassTransit code looks like this:
sbc.Subscribe(subConfig =>
{
subConfig.Handler<CanAllocateLicensedDeviceRequest>((ctx, req) =>
{
bool result = this.licenceActions.CanAllocateLicensedDevice();
ctx.Respond<CanAllocateLicensedDeviceResponse>(new CanAllocateLicensedDeviceResponse() { Result = result });
});
}
I understand the need to have the request typed, but could I not have a generic "bool" return type that I respond with. Would the Guid not ensure it got to the right place?
You could use a single response type to avoid creating an "ok" response type for each request/response pairing.
You also do not need to use CorrelatedBy as the RequestId is automatically set for you on the SendRequest call from the client-end of the request/response conversation.
I have a class that Handles send & receive over a socket between my application and the network. This class uses other classes, including a low level sockket connection class and a PDU handler class that creates the messages to send and handles received data.
Now i use an event to signal my class that the low level connection class has data for it and i need to send that data to the PDU handler to convert to information the application can use and then hand the data to the application.
For future usage, i am trying to get the class to be as generic as possible, so that on future Server/Client projects i will need only to change the PDU handler to take under consideration the new operations availlable and how to handle the data.
All that is well underway and now i am facing the isssue of handing the data back to the app. For that, my logical approach is an event letting the app know data is ready for collection. For that i can either:
a) have one event and let the app sort out what kind of message it is through the operation code (doable)
b) Have one event per operation code and have the app subscribe to all of them and thus know at start what it is getting
Considering the idea of making things generic, and the approach stated in b, is there a way to dinamicly create events based on a given delegate signature at runtime?
e. g.
imagine you have opcodes in an enum called MyOperation1 and MyOperation2 and you have defined a delegate like:
public delegate void PDUEventHandler(ParamType Param, [...]);
and i want to define events called:
public event PDUEventHandler MyOperation1;
public event PDUEventHandler MyOperation2;
But if i add a new operation code i will need an event for it.
Can this events be created dinamicly or do i need to do it by hand?
If i need to do it by hand then i guess a single event would be better and handle things app side.
Perhaps what you need is a callback - essentially you pass to the event handler a delegate for it to execute when the handler is done. Here's a stackoverflow thread to give you an idea
In terms of event handlers & re-useability, perhaps you can extend EventArgs and have that delegate as a property.
EDIT:
I was thinking a single PDUEventHandler having common code and a "hole" where custom code is run. That custom code is passed to the handler as a delegate (i.e. a method) or even a class instance. But let's change that a little...
Sounds like you need a factory. In fact you're practically describing a factory.
Conceptually let go of the idea of passing special opcodes to an EventHandler per se, or having multi-signature PDUEventHandlers.
Create a PDUHandlerFactoryclass. The factory returns a customized instance as a general PDUHandler class reference. Then instead of a PDUEventHander you caller has a PDUHandler reference that points to the factory-custom instance.
The following example is clearly fictional but it resumes how validation is done on a code base I'm working with.
TypeA has two methods, with the following signatures:
public void FirstMethod(TypeB param)
public ValidationResult TryFirstMethod(TypeB param)
When FirstMethod is called it needs to perform validation on the parameter.
Hence it calls TryFirstMethod to retrieve an object representing the validation's result.
If the instance of ValidationResult says that everything's OK the execution continues otherwise an exception is thrown.
The utility of TryFirstMethod is that the caller, an hypothetical TypeC, can execute this method and check if the actual method would throw. By examining a property on ValidationResult.
Also, the instance of ValidationResult contains information on why the input was wrong, how to fix it and so on.
This justifies the need for this type instead of just, say, using a boolean.
In practice this works fairly well, it's quite easy to validate data and to return localized error messages to the user.
The only issue is that since certain checks are quite complex performing them two times becomes a little expensive.
They are initially done by the caller to make sure that the actual method won't throw.
And then again by the method in question to check that the input is valid.
I can't find a clean way to avoid having to perform the checks two times.
To make things more complex there is the fact that the solution should work with standard methods, constructors and also when TypeB is a "primitive" type like string or int.
It sounds like your core logic is something like this:
Validate TypeB (call TryFirstMethod).
If not valid, display error message.
If valid (and, presumably, other members are valid as well) then to perform operation on the data (as part of FirstMethod?).
The data operation (FirstMethod) re-validates the input.
If this is (somewhat) correct, you should be able to change your design into something like:
Call FirstMethod.
Validate data.
If invalid, throw validation exception.
If valid, perform data operation.
Your UI would then call FirstMethod and expect that the operation was successful unless an exception was thrown, in which case you'd display your validation messages as you do currently. With this design you only perform the validation a single time.
Since the first method is a void, why not just call it to begin with and have it return a ValidationResult?
Can you give us any context on why the first one and second one have the same code that -has- to be run twice?
You could simply have the first one fail and pass the error messages back to the user in that route...
The cleanest solution in my eyes would be a third method:
public void FirstMethod(TypeB param, ValidationResult alreadyPerformedResult)
So the user can make it's own check, call the desired function with the result of the check. So you can skip the check and just test if the results of the test also meets your criterias too.
Maybe you can add something to your ValidationResult (e.g. function name as string in simplest scenario) so that you're sure, that the given result is really from this method and not from another called TryMethod().
being the C# newbie that I undoubtedly am, I'm a bit confused that you cannot set a return type on the DownloadStringCompletedEventHandler when using WebClient and the DownloadStringAsync method. Say I wanted to write some generic methods to return the HTML content of any web page, how would I go about returning the string if you cannot set a return type. I feel i'm missing something obvious here, any help would be appreciated!
Thanks!
The idea is that you're called back by the WebClient when the data is ready - when you subscribe to the event, you're basically saying "call this when you've finished". When you return from the callback, you're not returning to your code, you're returning back to WebClient. Why would it want to know the string, when it's just given it to you? :)
No, the idea is that your callback does what it needs to with the data (in the Result property of the event argument). That might mean stashing it somewhere, or writing it to the file system - whatever you need to do.
Don't worry - thinking asynchronously is tricky. You'll get there though :)
You don't set a return type because this is using the standard even handler pattern for callbacks (i.e. and Object sender and EventArgs for arguments)
The content of the page will be encapsulated in the DownloadStringCompletedEventArgs which get passed to the callback method (more specifically DownloadStringCompletedEventArgs.Result contains the downloaded data).
DownloadStringCompletedEventHandler is an event handler. In other words, it is a method that the class calls when it is finished downloading the string from the source. The results of the event are contained within the parameters. so, you attach to the event and then in your method, you use the parameters however you want to.
hope this helps.