I have a C# Windows Service that routes incoming emails and twitter comments to available Agents (I don't really - but the app does something very similar). So, I have a list of Agents, and logic to route these emails and tweets to available agents.
How does my code look?
I have an AgentManager class that keeps track of which agents are available, their skill levels, etc.
I have an EmailManager class that routes Emails to Agents.
I have a TwitterManager class that routes Tweets to Agents.
So - logic pertaining to Agents, such as the list of Agents, who is available, who has capacity for a Tweet, who has capacity for an Email, etc is all in the AgentManager.
Now, when EmailManager detects that there is a new email and needs to assign it to an Agent, I want
to get my list of agents from AgentManager(rather than going back to the database or keeping a separate list of Agents in EmailManager).
My initial thought is to pass AgentManager to EmailManager by reference. The reason I want to do this is so as Agents change state, are added/removed, etc - EmailManager will always be working wit
h the latest AgentManager (and therefore the latest Agent list). Somehow - this feels dirty. I know it is out of fashion to pass by ref, but it seems to be a good way to handle this. Am I doing it wrong?
EDIT:
I am passing the AgentManager by reference for storage, not to change it in the EmailManager class.
From your descriptions seems more soud to go the other way.
An AgentManager process EMails and Tweets and knows everything of its Agents -
So it should have a method that receive a list of EMails/Tweets and process them.
Because we are speaking of reference-types the question about passing by ref is a bit unclear.
For example:
AgentManager ag = new AgentManager();
EMailManager eg = new EMailManager();
TweetManaget tg = new TweetManager();
eg.LoadEMail();
List<EMails> mails = eg.GetMailsList();
tg.LoadTweet();
List<Tweets> tws = tg.GetTweetsList();
ag.ProcessData(mails, tws);
EDIT: Looking at the comment from OP I have thought of another strategy
Let the EMailManager and TweetManager declare an Event to which the AgentManager subscribe-
eg.EmailReceived += ag.NotifyEmail;
tg.TweetPolled += ag.NotifyTweet;
public class EventManager
{
public delegate void OnMailReceived(EMails m);
public event MailReceived;
........
private void GetMail()
{
EMails m;
.....
if(MailReceived != null)
MailReceived(m);
}
}
public class AgentManager()
{
public void NotifyEMail(EMails m)
{
.....
}
}
Related
I'm trying to implement DDD in my small project but Not able to understand how to raise domain event in below case.
Account Domain
public class Account : BaseEntity
{
public string PhoneNumber { get; set; }
public int OTP { get; set; }
public Account()
{
}
public Account(string phoneNumber, short otp)
{
this.PhoneNumber = phoneNumber;
this.OTP = otp;
CreatedDate = DateTime.Now;
RowKey = Guid.NewGuid().ToString();
PartitionKey = phoneNumber;
}
}
Account Service
public async Task<bool> GenerateOTP(string phoneNumber)
{
if (phoneNumber.Length != 10)
throw new ArgumentException(ApplicationConstraint.InvalidNumber);
var otp = Convert.ToInt16(new Random().Next(1000, 9999));
var account = new Account(phoneNumber, otp);
await this.accountRepository.AddEntity(account);
return true;
}
Account Repository Azure Storage table is my database
public virtual async Task AddEntity(TEntity entity)
{
TableOperation insertOperation = TableOperation.Insert(entity);
await table.ExecuteAsync(insertOperation);
}
I want to raise domain event only when data get saved in the database. For a workaround, I'm calling messaging service from account service.
Given the limited information provided, one option would be to create an AccountCreated event, (or an EntityCreated event if this is a cross-cutting concern) and publish it through some bus where consumers can asynchronousle receive it and do any subsequent processing needed.
The event need not use domain entities, and it can contain the information/data necessary to do any subsequent processing without the need to access a shared db (and as such adhering to DDD & microservice guidelines).
----Edit----
In the above I assumed that this is an established system and Azure storage isn't something that can change. Publishing an event, and handling it is pretty simple, but there are some things you need to be aware of. In general, you have 3 options here:
Publishing right after saving isn't wrong. It's simple way to do it, and (if you adopt an event-first methodology) you can do it in a generic way across your entities, minimal work. However, you need to be concious of how to deal with errors. Specifically, the issue is that if you store the entity first, before publishing the event, and then the process crashes for whatever reason, the event may be missed, so later workflows will not kick-off. If you do the reverse (publish then store), you run the risk of double-publishing the event. In this case you have two options:
If you store-then-publish: just accept the (really rare) possiblity of not publishing an event. This is something you need to speak to the business, and you can minigate the severity by logging the event before trying to save the entity.
If you publish-then-store: (you'll need to do this if the cost of fixing any issues ad-hoc are too great) you can fix the problem by having your consumers check the id of the incoming message if they ever have processed it before and reject it if they did OR make the process idempotent (if possible), meaning that doing the process twice isn't a problem
Using event sourcing. This isn't difficult in my opinion, but obviously it's an overhead if this is a a simple application, and while not difficult, it does need a significant amount of reading up if you're not familiar with it. If this is a non-trivial application, event sourcing can help a lot, because observers can just observe the events in the buffer and respond to that (so not need to explicitly publish the changes).
Append the event in a separate table within the same transaction where you're storing the entity, and use the outbox pattern implementation (publish those events from a separate service, marking them as published once they've been published). Honestly, the pattern shown on that is a bit simplistic, and there are a lot of tricky and small complexities, so prefer to use an existing one if you can find.
Honestly, if you can get away with 1.1, do that. It's simple and problems only very rarely appear. Just log the operation before you do it so that you can manually do it in the rare case of issues.
I just started to learn C# for a school project but I'm stuck on something.
I have a solution with 2 projects (and each project has a class), something like this:
Solution:
Server (project) (...) MyServerClass.cs, Program.cs
App (project) (...) MyAppClass.cs, Program.cs
In my "MyServerClass.cs", I have this:
class MyServerClass
{
...
public void SomeMethod()
{
Process.Start("App.exe", "MyAppClass");
}
}
How can I properly send, for example, an IP address and port? Would something like this work?
class MyServerClass
{
....
public void SomeMethod()
{
string ip = "127.0.0.1";
int port = 8888;
Process.Start("App.exe", "MyAppClass " + ip + " " + port);
}
}
Then in my "MyAppClass.cs", how can I receive that IP address and port?
EDIT:
The objective of this work is to practice processes/threads/sockets. The idea is having a server that receives emails and filter them, to know if they're spam or not. We got to have 4 or 5 filters. The idea was having them as separated projects (ex: Filter1.exe, Filter2.exe, ...), but I was trying to have only 1 project (ex: Filters.exe) and have the filters as classes (Filter1.cs, Filter2.cs, ...), and then create a new process for each different filter.
I guess I'll stick to a project for each filter!
Thanks!
There are a number of ways to achieve this, each with their own pros/cons.
Some possible solutions:
Pass the values in on the command line. Pros: Easy. Cons: Can only be passed in once on launch. Unidirectional (child process can't send info back). Doesn't scale well for complex structured data.
Create a webservice (either in the server or client). Connect to it and either pull/push the appropriate settings. Pros: Flexible, ongoing, potentially bi-directional with some form of polling and works if client/server are on different hosts. Cons: A little bit more complex, requires one app to be able to locate the web address of the other which is trivial locally and more involved over a network.
Use shared memory via a memory mapped file. This approach allows multiple processes to access the same chunk of memory. One process can write the required data and the others can read it. Pros: Efficient, bi-directional, can be disk-backed to persist state through restarts. Cons: Requires pointers and an understanding of how they work. Requires a little more manipulation of data to perform a read/write.
There are dozens more ways. Without knowing your situation in detail, it's hard to recommend one over another.
Edit Re: Updated requirements
Ok, command line is definitely a good choice here. A quick detour into some architecture...
There's no reason you can't do this with a single project.
First up, use an interface to make sure all your filters are interchangeable. Something like this...
public interface IFilter {
FilterResult Filter(string email);
void SetConfig(string config);
}
SetConfig() is optional but potentially useful to reconfigure a filter without a recompile.
You also need to decide what your IFilter's FilterResult is going to be. Is it a pass/fail? Or a score? Maybe some flags and other metrics.
If you wanted to do multiple projects, you'd put that interface in a "shared" or "common" project on its own and reference it from every other project. This also makes it easy for third parties to develop a filter.
Anyway, next up. Let's look at how the filter is hosted. You want something that's going to listen on the network but that's not the responsibility of the filter itself, so we need a network client. What you use here is up to you. WCF in one flavour or another seems to be a prime candidate. Your network client class should take in its constructor a network port to listen on and an instance of the filter...
public class NetworkClient {
private string endpoint;
private IFilter filter;
public NetworkClient(string Endpoint, IFilter Filter) {
this.filter = Filter;
this.endpoint = Endpoint;
this.Setup();
}
void Setup() {
// Set up your network client to listen on endpoint.
// When it receives a message, pass it to filter.Filter(msg);
}
}
Finally, we need an application to host everything. It's up to you whether you go for a console app or winforms/wpf. Depends if you want the process to have a GUI. If it's running as a service, the UI won't be visible on a user desktop anyway.
So, we'll have a process that takes the endpoint for the NetworkClient to listen on, a class name for the filter to use, and (optionally) a configuration string to be passed in to the filter before first use.
So, in your app's Main(), do something like this...
static void Main() {
try {
const string usage = "Usage: Filter.exe Endpoint FilterType [Config]";
var args = Environment.GetCommandLineArgs();
Type filterType;
IFilter filter;
string endpoint;
string config = null;
NetworkClient networkClient;
switch (args.Length) {
case 0:
throw new InvalidOperationException(String.Format("{0}. An endpoint and filter type are required", usage));
case 1:
throw new InvalidOperationException(String.Format("{0}. A filter type is required", usage));
case 2:
// We've been given an endpoint and type
break;
case 3:
// We've been given an endpoint, type and config.
config = args[3];
break;
default:
throw new InvalidOperationException(String.Format("{0}. Max three parameters supported. If your config contains spaces, ensure you are quoting/escaping as required.", usage));
}
endpoint = args[1];
filterType = Type.GetType(args[2]); //Look at the overloads here to control where you're searching
// Now actually create an instance of the filter
filter = (IFilter)Activator.CreateInstance(filterType);
if (config != null) {
// If required, set config
filter.SetConfig(config);
}
// Make a new NetworkClient and tell it where to listen and what to host.
networkClient = new NetworkClient(endpoint, filter);
// In a console, loop here until shutdown is requested, however you've implemented that.
// In winforms, the main UI loop will keep you alive.
} catch (Exception e) {
Console.WriteLine(e.ToString()); // Or display a dialog
}
}
You should then be able to invoke your process like this...
Filter.exe "127.0.0.1:8000" MyNamespace.MyFilterClass
or
Filter.exe "127.0.0.1:8000" MyNamespace.MyFilterClass "dictionary=en-gb;cutoff=0.5"
Of course, you can use a helper class to convert the config string into something your filter can use (like a dictionary).
When the network client gets a FilterResult back from the filter, it can pass the data back to the server / act accordingly.
I'd also suggest a little reading on Dependency Injection / Inversion of control and Unity. It makes a pluggable architecture much, much simpler. Instead of instantiating everything manually and tracking concrete instances, you can just do something like...
container.Resolve<IFilter>(filterType);
And the container will make sure that you get the appropriate instance for your thread/context.
Hope that helps
From my client/server I receive serialized data, once the data is deserialized, it goes into a command handler where receivedData.Action is the ClientMessage:
Command._handlers[receivedData.Action].Handle(receivedData.Profile);
The command handler will work out the client message and return the response that should be given to the client.
I have an enum for the client messages as follow:
public enum ClientMessage
{
INIT = 1,
NEW_PROFILE,
UPDATE_PROFILE_EMAIL,
UPDATE_PROFILE_PASSWORD,
UPDATE_PROFILE_PHONE,
UPDATE_PROFILE_DATE,
UPDATE_PROFILE_SECRET_ANSWER,
UPDATE_PROFILE_POSTAL_CODE,
UPDATE_SUCCESS,
PING,
PONG,
QUIT
}
What I am having a difficult is how to have all the actions written, for example:
Should I have a separated enum for what the client sends and another for what the server should reply with ?
Or should I have a single enum with all messages and follow it as requested ?
Or how should I go about defining the messages and handling it ?
This is what my server/client currently does just to give you a better view:
Server starts
Client connects
Client send auth to server
Server verify client and send connected approval message
Client will from there start sending and updating profiles to the server
This is roughly an example only.
IPacketHandler
public interface IPacketHandler
{
MyCommunicationData Handle(ProfileData profile);
}
Command
public class Command
{
public static Dictionary<ClientMessage, IPacketHandler> _handlers = new Dictionary<ClientMessage, IPacketHandler>()
{
{ClientMessage.INIT, new Init()},
{ClientMessage.NEW_PROFILE, new NewProfile()},
{ClientMessage.UPDATE_PROFILE_EMAIL, new UpdateEmail()},
{ClientMessage.UPDATE_PROFILE_PASSWORD, new UpdatePassword()},
{ClientMessage.UPDATE_PROFILE_PHONE, new UpdatePhone()},
{ClientMessage.UPDATE_PROFILE_DATE, new UpdateDate()},
{ClientMessage.UPDATE_PROFILE_SECRET_ANSWER, new UpdateSecretAnswer()},
{ClientMessage.UPDATE_PROFILE_POSTAL_CODE, new UpdatePostalCode()},
{ClientMessage.UPDATE_SUCCESS, new Success()},
{ClientMessage.PING, new Ping()},
{ClientMessage.PONG, new Pong()},
{ClientMessage.QUIT, new Quit()},
};
}
Example of the INIT
public class Init : IPacketHandler
{
public MyCommunicationData Handle(ProfileData profile)
{
// Some verification to auth the client here
// bla bla
// return response
return new MyCommunicationData() { Action = ClientMessage.CONNECTED };
}
}
PS: If my title is off and you have a better suggestion let me know or if you can go ahead and update it, I was not sure of how to describe this in English.
If your question is about how to design the class and interactions as I understood it, then I would - and it's totally dependant on the specifics of your application - separate this big Enumerations type into separate, smaller ones that are more descriptive of what they do, and of your intentions, for example, ProfileAction, ActionResult, PingStatus etc.. Then when you're using these enums, you make sure that you get compiler-time checks that you're doing it correctly, otherwise, what you're doing is almost like just passing strings.
It also has to do with sticking to Single Responsibility principle in OO design: an object should have single responsibility. Your enum as it stands now has more than one responsibility.
With issues like these, I find it helpful to look at what .NET framework does: for example look at Ping class and how it uses PingStatus enumerations and other enumerations as well.
Not sure I'd use an enum at all. They are great inside a peice of code, exposed as communicated value, they are considerably less than great.
For me I'd have a different class per message, not one message with a god property.
I am working on a website and we will need to send the user some email notifications when some actions happen on the website, such as if someone else sent the user a message or invite him to an event.
Is there a standard good way to attach a notification to any method without changing the method code?
For example I was thinking if I can put an attribute on the method this attribute will make this method to call the notification module with some parameters.
note: I am working on an ASP.Net MVC 3 website, using entity framework codefirst.
I do not believe there is a standard process.
Aspect Oriented approaches (such as attributes) can be handy only if there are used in conjunction with AOP frameworks (such as AspectSharp) or when used on the MVC Action itself: you can use action filters to achieve the requirement and send use the notification if the events are mapped to MVC actions.
Event Listeners. You do have to change the code, but you don't actually send the email within the code.
Basically, any code that does stuff that other code might be interested in has hooks so that listeners can attach to it and listen for events.
In Pseudo-java:
public class OrderProcessor {
protected final List<OrderProcessorListener> listeners = new ArrayList<OrderProcessorListener>();
public void addListener(OrderProcessorListener orderProcessorListener) {
listeners.add(orderProcessorListener);
}
public void notifyListeners(OrderProcessorEvent event) {
for(OrderProcessorListener listener : listeners) {
listener.handle(event);
}
}
public void randomMethod() {
// ... do stuff
notifyListeners(new SomeEvent(...)); // notify listeners
}
public interface OrderProcessorListener {
public void handle(OrderProcessorEvent event);
}
}
then, other interested code can do...
public class EmailSender implements OrderProcessorListener {
public void handleEvent(OrderProcessorEvent event) {
// do whatever...
}
}
When you construct your OrderProcessor and your EmailSender, you then add the EmailSender as a listener and voila. You can use this pattern everywhere you need to react to actions from a piece of code- and you don't need to put the actions in the same code...
Would be pretty hard without any change to the original code. How would you know an action succeeded? And what type of notification should be sent, to whom, etc.
If not changing the original code is a must, you could do it in a hacky way: add a global filter, inspect the controller name, action name, the action result, and maybe you could decide from those parameters if an email should be sent. But this would be extremely fragile, and a maintenance nightmare.
Unless your notifications are extremely simple, like always send e-mail to all event attendees, if any modification is done to the event. But that could cover only some of the basic use-cases...
IMO it would be better if you integrated sending notifications into your existing code. If you extend the meaning of a repository (and you use one) to "take database actions, and anything else related to creation/update/delete of an object".
No changes to controller actions, and your EventRepository.Create/Modify methods would know already have all the parameters to send the notifications...
This link http://msdn.microsoft.com/en-us/library/aa772153(VS.85).aspx says:
You can register up to five notification requests on a single LDAP connection. You must have a dedicated thread that waits for the notifications and processes them quickly. When you call the ldap_search_ext function to register a notification request, the function returns a message identifier that identifies that request. You then use the ldap_result function to wait for change notifications. When a change occurs, the server sends you an LDAP message that contains the message identifier for the notification request that generated the notification. This causes the ldap_result function to return with search results that identify the object that changed.
I cannot find a similar behavior looking through the .NET documentation. If anyone knows how to do this in C# I'd be very grateful to know. I'm looking to see when attributes change on all the users in the system so I can perform custom actions depending on what changed.
I've looked through stackoverflow and other sources with no luck.
Thanks.
I'm not sure it does what you need, but have a look at http://dunnry.com/blog/ImplementingChangeNotificationsInNET.aspx
Edit: Added text and code from the article:
There are three ways of figuring out things that have changed in Active Directory (or ADAM). These have been documented for some time over at MSDN in the aptly titled "Overview of Change Tracking Techniques". In summary: Polling for Changes using uSNChanged. This technique checks the 'highestCommittedUSN' value to start and then performs searches for 'uSNChanged' values that are higher subsequently. The 'uSNChanged' attribute is not replicated between domain controllers, so you must go back to the same domain controller each time for consistency. Essentially, you perform a search looking for the highest 'uSNChanged' value + 1 and then read in the results tracking them in any way you wish. Benefits This is the most compatible way. All languages and all versions of .NET support this way since it is a simple search. Disadvantages There is a lot here for the developer to take care of. You get the entire object back, and you must determine what has changed on the object (and if you care about that change). Dealing with deleted objects is a pain. This is a polling technique, so it is only as real-time as how often you query. This can be a good thing depending on the application. Note, intermediate values are not tracked here either. Polling for Changes Using the DirSync Control. This technique uses the ADS_SEARCHPREF_DIRSYNC option in ADSI and the LDAP_SERVER_DIRSYNC_OID control under the covers. Simply make an initial search, store the cookie, and then later search again and send the cookie. It will return only the objects that have changed. Benefits This is an easy model to follow. Both System.DirectoryServices and System.DirectoryServices.Protocols support this option. Filtering can reduce what you need to bother with. As an example, if my initial search is for all users "(objectClass=user)", I can subsequently filter on polling with "(sn=dunn)" and only get back the combination of both filters, instead of having to deal with everything from the intial filter. Windows 2003+ option removes the administrative limitation for using this option (object security). Windows 2003+ option will also give you the ability to return only the incremental values that have changed in large multi-valued attributes. This is a really nice feature. Deals well with deleted objects. Disadvantages This is .NET 2.0+ or later only option. Users of .NET 1.1 will need to use uSNChanged Tracking. Scripting languages cannot use this method. You can only scope the search to a partition. If you want to track only a particular OU or object, you must sort out those results yourself later. Using this with non-Windows 2003 mode domains comes with the restriction that you must have replication get changes permissions (default only admin) to use. This is a polling technique. It does not track intermediate values either. So, if an object you want to track changes between the searches multiple times, you will only get the last change. This can be an advantage depending on the application. Change Notifications in Active Directory. This technique registers a search on a separate thread that will receive notifications when any object changes that matches the filter. You can register up to 5 notifications per async connection. Benefits Instant notification. The other techniques require polling. Because this is a notification, you will get all changes, even the intermediate ones that would have been lost in the other two techniques. Disadvantages Relatively resource intensive. You don't want to do a whole ton of these as it could cause scalability issues with your controller. This only tells you if the object has changed, but it does not tell you what the change was. You need to figure out if the attribute you care about has changed or not. That being said, it is pretty easy to tell if the object has been deleted (easier than uSNChanged polling at least). You can only do this in unmanaged code or with System.DirectoryServices.Protocols. For the most part, I have found that DirSync has fit the bill for me in virtually every situation. I never bothered to try any of the other techniques. However, a reader asked if there was a way to do the change notifications in .NET. I figured it was possible using SDS.P, but had never tried it. Turns out, it is possible and actually not too hard to do. My first thought on writing this was to use the sample code found on MSDN (and referenced from option #3) and simply convert this to System.DirectoryServices.Protocols. This turned out to be a dead end. The way you do it in SDS.P and the way the sample code works are different enough that it is of no help. Here is the solution I came up with:
public class ChangeNotifier : IDisposable
{
LdapConnection _connection;
HashSet<IAsyncResult> _results = new HashSet<IAsyncResult>();
public ChangeNotifier(LdapConnection connection)
{
_connection = connection;
_connection.AutoBind = true;
}
public void Register(string dn, SearchScope scope)
{
SearchRequest request = new SearchRequest(
dn, //root the search here
"(objectClass=*)", //very inclusive
scope, //any scope works
null //we are interested in all attributes
);
//register our search
request.Controls.Add(new DirectoryNotificationControl());
//we will send this async and register our callback
//note how we would like to have partial results
IAsyncResult result = _connection.BeginSendRequest(
request,
TimeSpan.FromDays(1), //set timeout to a day...
PartialResultProcessing.ReturnPartialResultsAndNotifyCallback,
Notify,
request);
//store the hash for disposal later
_results.Add(result);
}
private void Notify(IAsyncResult result)
{
//since our search is long running, we don't want to use EndSendRequest
PartialResultsCollection prc = _connection.GetPartialResults(result);
foreach (SearchResultEntry entry in prc)
{
OnObjectChanged(new ObjectChangedEventArgs(entry));
}
}
private void OnObjectChanged(ObjectChangedEventArgs args)
{
if (ObjectChanged != null)
{
ObjectChanged(this, args);
}
}
public event EventHandler<ObjectChangedEventArgs> ObjectChanged;
#region IDisposable Members
public void Dispose()
{
foreach (var result in _results)
{
//end each async search
_connection.Abort(result);
}
}
#endregion
}
public class ObjectChangedEventArgs : EventArgs
{
public ObjectChangedEventArgs(SearchResultEntry entry)
{
Result = entry;
}
public SearchResultEntry Result { get; set;}
}
It is a relatively simple class that you can use to register searches. The trick is using the GetPartialResults method in the callback method to get only the change that has just occurred. I have also included the very simplified EventArgs class I am using to pass results back. Note, I am not doing anything about threading here and I don't have any error handling (this is just a sample). You can consume this class like so:
static void Main(string[] args)
{
using (LdapConnection connect = CreateConnection("localhost"))
{
using (ChangeNotifier notifier = new ChangeNotifier(connect))
{
//register some objects for notifications (limit 5)
notifier.Register("dc=dunnry,dc=net", SearchScope.OneLevel);
notifier.Register("cn=testuser1,ou=users,dc=dunnry,dc=net", SearchScope.Base);
notifier.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(notifier_ObjectChanged);
Console.WriteLine("Waiting for changes...");
Console.WriteLine();
Console.ReadLine();
}
}
}
static void notifier_ObjectChanged(object sender, ObjectChangedEventArgs e)
{
Console.WriteLine(e.Result.DistinguishedName);
foreach (string attrib in e.Result.Attributes.AttributeNames)
{
foreach (var item in e.Result.Attributes[attrib].GetValues(typeof(string)))
{
Console.WriteLine("\t{0}: {1}", attrib, item);
}
}
Console.WriteLine();
Console.WriteLine("====================");
Console.WriteLine();
}