Handling a dependancy from different project in a console application - c#

I have the following project structure in my solution:
Project.Repository (Class Library)
Project.Core (Class Library)
Project.Web (MVC5 web front end)
Project.Scheduler (Console Application)
I am using Unity to handle my DI.
My problem
I have a method which sits in the Core layer, this method has a dependency on an IProcessDataService interface which is being handled in my Unity config.
//Service
container.RegisterType<IProcessDataService, ProcessDataService>(new PerRequestLifetimeManager());
I have most recently created my Console Application project which will basically invoke the said method and will be run on a windows schedule.
How do I go about accessing this method from my Console Application's static Main method considering I have a dependency to my core interface?
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Begin Automation Process");
//Run method from Core layer which has a dependency on IProcessDataService
}
}

your console app's main method is your composition root and you should be doing all of your wiring up in there.
Then you can resolve your object from the container and call the method on it.

Related

Using IoC container in two C# apps with events

I have two projects in a Visual Studio solution where one is a console app and the other is a WPF app. Both have a composite root where a common bootstrapper is instantiated in each and registers some common types.
I'm trying to get the console app to subscribe to some events published by the WPF app. When a WPF window is moved, opened, or resized, the console app prints a string on the console.
The Bootstrapper class is in a separate class library with the following code:
public class Bootstrapper
{
public void Initialize()
{
var container = IocContainer.Instance.Container;
container.Register<IOrderRepository, SqlOrderRepository>(Lifestyle.Singleton);
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<IEventPublisher, EventPublisher>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
container.Register<IViewsIntegrationService, ViewsIntegrationService>(
Lifestyle.Singleton);
try
{
// Verify the container
container.Verify();
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
System.Console.ReadLine();
}
}
}
Both apps have this code in the composite root:
var bs = new Bootstrapper();
bs.Initialize();
The ViewsIntegrationService fires the events in the WPF app.
The Console app subscribes to the ViewsIntegrationService events.
When I run both applications, the console app does not receive the events and nothing prints on the console.
Is it because each of the apps use separate instances of the bootstrapper? Hence two sets of identical registrations? Or is this not working because of another reason?
Despite being 2 projects in the same Visual Studio solution, when compiled each one is an individual Windows executable program. These two programs will not automatically communicate with each other. If you need to transfer information from one program to the other, you will need to use some sort of communication channel such as TCP or MSMQ. See Send/Receive message To/From two running application.
Alternatively, you could make your "console application" into a class library (which when referenced from WPF will be part of the same application) and use a WPF window that looks like a console application window write out information.
Events and dependency injection only affect a single application, so neither are relevant in the case you are communicating across application boundaries.

Windows Service - WCF Service Design

I have a Windows Service that hosts a WCF service and I am successfully able to connect to it using WCFTestClient and a Custom Client. The windows service is based upon what used to be an exe, but since the program will be used for a long running process on a server, the service is a better route. The problem is that I cannot access static variables in the application from the WCF service.
In the .exe (I switched this to a .dll which is the server application) I use a global class implemented as such:
public static class Globals
{
....
}
This holds references to the major parts of the program so that if any part needs to reference another I can use the syntax Globals.JobManager.RunJob().
The problem that I am encountering is that the WCF service is not able to reference Globals at run-time. One example of where I need this to be done is in the GetJob method:
public class ConsoleConnection : IConsoleConnection
{
public string[] RetrieveJobList()
{
string[] jobs = Globals.JobManager.GetAllJobNames().ToArray();
return jobs;
}
}
This method returns null when tested in WCFTestClient and throws an exception in the created client.
I believe this issue to be caused by the way the Windows Service, WCF Service, and the application DLL are initiated. The current method is such:
public class ETLWindowsService : ServiceBase
{
....
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
Globals.InitializeGlobals();
serviceHost = new ServiceHost(typeof(ConsoleConnection));
serviceHost.Open();
}
....
}
Here the Windows Service starts, Calls the Globals.InitializeGlobals() that creates all the necessary parts of the application, then starts the WCF service (If this is the wrong way to do this, let me know. I'm piecing this together as I go). I'm assuming that these actions are being done in the wrong order and that is the cause of the problems.
Do I need to have the Windows Service create the WCF Service which in turn creates the application (this doesnt make sense to me), or do I have the Windows Service create the application which then creates the WCF Service? Or is there a third option that I am missing?
The application is in a .dll with the WCF in a separate .dll
I totally agree with Andy H.
If I review this kind of code, I won't try to make the stuff work with the global static variable (even if in the end this is probably possible). A static global class is smelly. First of all, I will figure out to make it work without it.
There are several solution: dependency injection, messaging communication, event driven...
To help you: a long running process in a web service is very common, youy have a good description
here. But in any case, it never uses a static class to synchronize the jobs :)
Improve your design, and you will see that your current problem won't exist at all.

Dependency Injection and project structure for Console applications

I have 4 projects:
Core (IServer):
System
System.Core
DependencyResolver:
Core
StructureMap
Infrastructure (Service):
Core
External dependency
Console:
Core
DependencyResolver
Requierements:
I am trying to use StructureMap only in the DependencyResolver.
Furthermore the Console application should not know anything about Infrastucture.
When I do not want to reference StructureMap on my Console Application I have to build a ServiceLocator.
In the DependencyResolver I have a Bootstrapper that is responsible for calling StructureMap registry stuff (Register)
In my Console application I want to get an instance. For this I need to reference StructureMap. Another way would be to write a little wrapper around StructureMaps resolving methods.
Is there any other better way of decoupling the console from StructureMap?
While I see a reason for separating IoC register,resolve,release from the implementation of the application, I don't see any reason why the IoC container shouldn't be in the console application (the composition root) and the application implemention in another assembly instead.
That way the console application is very easy:
Create the container
Load the container configuration
Resolve the Application
Call run on the application and pass the console arguments along
dispose the container when the application exits the run method
With SM it look about like this:
public void Main(params string[] args)
{
using (var container = new Container())
{
container.LoadAllConfigurationModules();
container.AddRegistry<SomeRegistry>();
container.GetInstance<Application>().Run(args);
}
}
For things you can't create at startup you create a factory interface in your application assembly:
interface ISomeFactory { ISomeDependency CreateSomeDependency() }
and implement this interface in the console application by injecting the container and use it to resolve the instance. I guess the SM implementation looks like this:
public class SomeFactory : ISomeFactory
{
public SomeFactory(IContainer sontainer) { this.container = container; }
ISomeDependency CreateSomeDependency() { this.container.GetInstance<ISomeDependency>(); }
}
Other IoC container even have the functionallity to implement these interface factories automatically.

How do I Unit Test NServiceBus.Configure.WithWeb()?

I'm building a WCF service that receives requests on an external IP and translates them into messages that are sent via NServiceBus.
One of my unit tests invokes Global.Application_Start(), which performs the configuration of the application, and then attempts to resolve the web service to
validate that the container can build up all of the dependencies.
This works fine when I'm using Configure.With() in my windows services, but
the call to Configure.WithWeb() fails in this context (presumably because the "bin"
directory does not exist?).
Is it possible to unit test a method that calls Configure.WithWeb(), or should I
just use the overload for Configure.With() that takes a directory name?
I created a new startup class like so:
public class NonWebRunAtStartup : IRunAtStartup
{
public void InitializeInfrastructure(object container)
{
Configure.With()
.StructureMapBuilder((IContainer) container)
.Log4Net()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.LoadMessageHandlers()
.CreateBus()
.Start();
}
}
Then in my test, I ensured that my IOC container would use this one instead of the usual web-based one by adding this to my test:
IoC.Register<IRunAtStartup, NonWebRunAtStartup>();
This got me to a different error, which I'm still fighting with, which I'll ask as a separate question (now NSB can't load assemblies that are in NServiceBus.Core.dll, such as Antlr3.Runtime.dll).

What is the accepted pattern for an application that can be run as a service or as a console application

I have a project that is deployed to production as a windows service. However for local development purposes it would be useful to run it as a console application. At the moment I have a class Called ReportingHost that provides my core functionality, And a class called ReportingServiceHost that inherits from ServiceBase and allows me to run the application as a service. There is also a program class with a main method that calls ServiceBase.Run on my ReportingServiceHost.
I think I need to write a ReportingConsoleHost class that allows me to run the functionality in a console. Then I need to modify my Main to react to a command line switch and choose one or the other. These are the two bits I am having trouble with.
I have had a look at this and attempted to use that code but my app exits immediately, it doesn't show a console window and it doesn't wait for Enter before closing.
Part of the problem is that I dont have a deep understanding of how these things work. a definitive pattern for splitting my functionality, my two different ways of running that functionality, and a main method that chooses one of these ways based on a command line argument is what I am hoping to achieve.
I suspect your test project was configured as a windows exe, not a console exe. With a windows exe Console.ReadLine will return immediately.
To have a console exe that works both as a service and at the command line, start it as a service project (in Visual Studio) - and add a check on Environment.UserInteractive - i.e.
static void Main() {
if(Environment.UserInteractive) {
// code that starts the listener and waits on ReadLine
} else {
// run the service code that the VS template injected
}
}
You can of course also use a command line switch. I have example on microsoft.public.dotnet.languages.csharp that acts as:
an installer / uninstaller
a service
a console-mode app
depending on the switches
I have done this before by implementing a normal Windows Service (by deriving from ServiceBase), but putting a check in the main method to check for a command line argument.
If the args contain /console, start the console version, otherwise start the service.
Something like this:
internal class MyService : ServiceBase
{
internal static void Main(string[] args)
{
if (args.Length == 0)
{
// run as a service....
ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()};
Run(servicesToRun);
}
else
{
// run as a console application....
}
}
}
My advise? Put all your logic for your service in a separate assembly. (A class library or DLL.) Then create one project as service which references your class library and puts the code to use as services. Create a second console project which also references your class library but which will make it available as a console application.
You would end up with three different projects in your solution but it does allow you to keep things separate. Actually, this would make it possible to extend your service in several other shapes too. You could, for example, create a 4th project as a web service and thus call your service from a web browser on a client system. Because the software logic is separated from the usage logic, you gain lots of control over it.
Be aware that a service will possibly run with more limitations than a console application. In general, services don't have network access by default, don't have a monitor assigned to them to display error messages and in general run with a limited user account or system account. Your service might work as a console yet fail as a service because of this.
There are already two good answers above - but I thought I'd post a link to Brian Noyes' Debuggable Self-Host Windows Service Project blog post - it talks about WCF but should apply to any 'Windows Service'.
The best thing is the sample code - if you can't figure out where the above examples 'fit', grab the complete project and see how it works. Thanks Brian!

Categories

Resources