I have a Service Fabric application with one service which is exposed to Internet (GatewayService) through an ASP.NET Web API and a couple of internal services not exposed to the Internet (let's call one of them InternalService). So far, InternalService is also an ASP.NET Web APIs, so InternalService.cs has a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] {
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.ConfigureServices((context, services) => { services.AddSingleton(serviceContext); })
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build()))
};
}
The Startup class (in Startup.cs) for InternalService configures some services, such as adding a SQL DbContext to the Dependency Injection system, and of course setting up ASP.NET with AddMvc() etc. I have a couple of ApiControllers which expose the API.
This works, BUT I don't get any real type safety with this, and it generally makes development a bit cumbersome, needing to deserialize the result manually in my GatewayService before manipulating it. So I decided to go with SF's Service Remoting instead, resulting in a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
Then I copied all the logic from the controllers into InternalService.cs too, but this lead to an issue: I don't have access to my DbContext anymore, because it was injected into the constructor of the ApiController, instantiated by ASP.NET according to the rules set in the Startup class, which isn't used anymore.
Is there a way for me to use Startup in the same way when using Service Remoting?
Can I separate the API into multiple classes, in the same way as ApiControllers are separated into multiple classes? I feel like having all exposed methods in the same class will be quite a hazzle.
I know this has already an accepted answer, but I want to add my two cents.
As you have realized, remoting has two major differences compared to WebApi:
Given a remoting interface, you have a single implementation class
The remoting implementation class is a singleton, so, even if you use DI as explained in the accepted answer, you still can't inject a DbContext per request.
I can give you some solutions to these problems:
This one is simple: create more interfaces. You can add as many remoting interfaces as you want in a single service fabric service. So, you should split your remoting API into smaller interfaces with groups that make sense (interface segregation). But, I don't think you should have many, because that would probably mean that your microservice has too many responsibilities.
A naive approach to having dependencies per request is to inject factories into the remoting class, so you can resolve and dispose dependencies in every method instead of by constructor injection. But I found a much better approach using Mediatr, which might not seem trivial, but once set up it's very easy to use. The way it works is you create a little helper class that gets an ILifetimeScope (as you use Autofac) in the constructor and it exposes an Execute method. This method will create a child LifetimeScope, resolve Mediatr and send a WrapperRequest<TRequest> (the wrapper is a trick so that the remoting input and output objects don't have to depend on Mediatr). This will allow you to implement a Handler class for each remoting operation, which will be resolved per request so that you can inject the dependencies in the constructor as you do with a WebApi controller.
It might sound confusing if you are not familiar with Mediatr and Autofac. If I have time I'll write a blog post about it.
You can use Autofac, there's an entire page that explains how to set it up:
Add the Autofac.ServiceFabric nuget package
Configure DI:
// Start with the trusty old container builder.
var builder = new ContainerBuilder();
// Register any regular dependencies.
builder.RegisterModule(new LoggerModule(ServiceEventSource.Current.Message));
// Register the Autofac magic for Service Fabric support.
builder.RegisterServiceFabricSupport();
// Register a stateless service...
builder.RegisterStatelessService<DemoStatelessService>("DemoStatelessServiceType");
// ...and/or register a stateful service.
// builder.RegisterStatefulService<DemoStatefulService>("DemoStatefulServiceType");
using (builder.Build())
{
ServiceEventSource.Current.ServiceTypeRegistered(
Process.GetCurrentProcess().Id,
typeof(DemoStatelessService).Name);
// Prevents this host process from terminating so services keep running.
Thread.Sleep(Timeout.Infinite);
}
check out the demo project.
Related
Let's say a dev has created a library that exposes a class ScheduledAction
All this class does is execute a method at a specified interval.
So you would use this way:
var scheduledAction = new ScheduledAction(methodToCall, 10000);
scheduledAction.Start();
Every 10 seconds, the methodToCall is executed.
Now let's say dev of the library decided that ScheduledAction will catch and log exceptions thrown by methodToCall.
To do this it needs a logger. As this is a library, the dev doesn't want to force the use of any particular logging library and or implementation. This should be controlled and configured by the application consuming the library.
This is a very simple example to illustrate the point.
While researching on this, I noticed a common approach is to expose some sort of contract for logging (via an interface) and the consuming application has to supply an implementation, which is "injected" via some sort of initialization method that the library exposes.
However logging may not be the only dependency a library needs from a consuming application.
I'm struggling to find concrete examples/best practices for such situations, in particular when building an application that uses an IoC container, like an Asp.NET Core Web App.
All the services are added to the container at startup. I would then need to "initialize" the above mentioned library passing in implementations of the required services, requesting them explicitly, which is pretty much using the container like a service locator and more importantly the instances passed to the library cannot be swapped later (I'm thinking of cases where the IoC container creates object based on options/configuration which may change even at run-time).
You have a few options available:
Expose an ILogger interface on the same lib assembly/package, and a Logger class. Have the Logger class expose a static method to set the internal logger instance to some class that implements it.
Instead of setting up an implementation of ILogger, one could just assign an Action to be executed by the static Logger class.
The important is to have this behavior exposed through an interface, so the ScheduleAction class can be easily tested.
Then, on the ScheduleAction class, just check if the Logger has the actual logger set, and call it when an exception occurs.
I'm having a web project that hosts both WCF and Web API V2 ApiControllers.
Both should benefit from using SimpleInjector.
There are 2 different nuget packages for the 2 techniques:
SimpleInjector.integration.WebApi
SimpleInjector.Ingegration.Wcf
As in the given case registrations should be identical for both, what is the best way to approach this?
Should I create 2 different containers, since the scope will anyway be valid only as long as the requests are open?
I currently implemented the following, to use the correct ScopedLifestyles:
public static void ConfigureForWCF(Container container)
{
container.Options.DefaultScopedLifestyle = new WcfOperationLifestyle();
RegisterImplementations(container);
}
public static void ConfigureForWebAPI(Container container)
{
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
RegisterImplementations(container);
}
public static void RegisterImplementations(Container container)
{
// registrations for both WCF and Web API in here
container.Register<IMyInterface, MyClass>();
and I know call them like that:
// container for WCF
var containerWCF = new Container();
SimpleInjectorConfiguration.ConfigureForWCF(containerWCF);
containerWCF.Verify();
// use the container for WCF
SimpleInjectorServiceHostFactory.SetContainer(containerWCF);
// container for Web API
var containerWebAPI = new Container();
SimpleInjectorConfiguration.ConfigureForWebAPI(containerWebAPI);
// this doesn't currently make sense for me as the controllers inheriting from ApiController get registered as Transient
//containerWebAPI.RegisterWebApiControllers(GlobalConfiguration.Configuration);
// instead I will register the Controllers manually
containerWebAPI.Verify();
// use the container for Web API
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(containerWebAPI);
Would it be possible to use the same Container eventually?
(calling Verify on both containers also doesn't make sense as long as they have identical registrations)
You've basically got 3 options:
Use two container instances
Use one container instance with a hybrid lifestyle that mixes the WebApiRequestLifestyle and WcfOperationLifestyle.
Use one container and use the same lifestyle for both WCF and Web API. This would typically be the AsyncScopedLifestyle.
Whether or not it is okay to have two containers depends on several values, such as the amount of services that should exist exactly once across the whole AppDomain. When you have 2 container instances, each get their own singleton instance, so you should provide each container with an existing instance. This can be troublesome, but in most cases it should not be a problem for a container to get its own singleton instance.
On the other side will having 2 containers mean that you will have to use some shared logic that can populate the registrations that both container instances share. This can complicate things.
On the other hand does having two containers allow both services to run in an isolated fashion, which can be beneficial.
If you choose to have one container instance, the use of a Hybrid lifestyle would be the most obvious solution, especially since the scoping technology used by WCF is different (based on ThreadScopedLifestyle) from the Web API scoping technology (which is based on AsyncScopedLifestyle). So, easiest solution is to register them as hybrid as follows:
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
defaultLifestyle: new WebApiRequestLifestyle(),
fallbackLifestyle: new WcfOperationLifestyle());
With this configuration, Simple Injector will use WebApiRequestLifestyle when there is an active Web API scope (which means a AsyncScopedLifestyle scope). In the absence of such scope, it will fallback to using the WcfOperationLifestyle.
This will be the easiest solution in case you wish to have one container.
The last option is to use one particular scoped lifestyle for both the WCF and the Web API application. Since Web API is inherently asynchronous, the only obvious lifestyle to use is AsyncScopedLifestyle. With ASP.NET Core we are actually moving away from custom framework-specific lifestyles and primarily use AsyncScopedLifestyle instead.
Although you can both use AsyncScopedLifestyle and WebApiLifestyle interchangeably in a Web API application, this doesn't hold for WCF. That's because the WCF integration package uses a technique that is similar to the ThreadScopedLifestyle, but uses its own implementation.
Although you can use the AsyncScopedLifestyle on single-threaded applications as well, you will have to replace part of the infrastructure for WCF that currently starts the WCF scope, to make it start an async Scope instead.
Since this is a bit more work to do, I would opt for either using 2 containers, or use the hybrid lifestyle.
I have the following code snippet in my application:
services.AddScoped<IMyInterface, MyService>();
services.AddSingleton<IYourInterface, YourService>();
Due to some environment initialization process, I have to be able to obtain the singleton instance of IYourInterface within Startup class to call the service to read a couple of configuration entries from a remote server and populate them. How can I achieve this goal considering the fact that I am using .Net Core's built-in DI framework?
The way to do this to create this instance manually up front as follows:
var service = new YourService();
services.AddScoped<IMyInterface, MyService>();
services.AddSingleton<YourService>(service);
Just as it is wise to separate the registration process from use (as the Microsoft.Extensions.DependencyInjection library correctly forces), this kind of separation is important between loading/building configuration and making the container registrations. Doing register-resolve-register is unsupported by libraries like MS DI, Autofac and Simple Injector, because it can lead to lots of complexity and subtle bugs.
An architectural question. I've got a nicely de-coupled MVC3 solution with a few projects that's working rather well.
Proj.Core - interfaces for data classes and services
Proj.Services - interfaces for model services
Proj.Data.NH - implementations of the data interfaces
Proj.Services.NH - implementations of the data / model services
Proj.Infrastructure - setting up Ninject and NHibernate
Proj.Tests - unit tests
Proj.Web - the MVC project
I've set up NHibernate to be session per request in the infrastructure project, so Proj.Web doesn't need to reference NHibernate (or Ninject, for that matter). I'm now introducing SignalR, which works really nicely for a quick chat app. I've put a SignalR hub in the web project. I now want to persist the chat messages in the database, which has confused me somewhat.
I want to use a service (let's call it PostService), so the SignalR hub doesn't have a dependency on NHibernate. My other services are injected into the controllers' constructors, and the session is injected into the services' constructors.
As the SignalR hub hangs around, unlike controllers, PostService (injected into the constructor as an IPostService) can't have a session injected into its constructor, as there won't be a session. If there was, it would hang around forever, which would be far too long a time for a transaction.
I could inject the session factory into the PostService, and each method could use a transaction, e.g.
private void WithTransaction(Action<ISession> action)
{
using (var session = _sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
action(session);
tx.Commit();
}
}
public IPost Post(string message)
{
WithTransaction(session =>
{
session.Save(new Post(message));
});
}
The hub will then call _postService.Post(message);
However, once the Post method does more things, I'll want to use some of my existing services to do the things, as they've already been written and unit tested. As the session is created in the method, I can't have the services injected into the PostService constructor, as they accept a session into their constructors.
So, I guess I have the following options, but I'm not sure if a) this is a complete list, or b) which is the best option:
I. Inject an IDependencyResolver into the PostService constructor, and create the services I need in the Post method, passing in the session to the constructor. There's an IDependencyResolver in System.Web.Mvc and in SignalR, so this would (depending on which project PostService resides) introduce a dependency on either library.
II. Modify the services so each method that uses a session has one passed in as a parameter. Overload this without the session parameter, and call the new one. The MVC service calls would use the first, and the PostService would use the second e.g.
public void SaveUser(IUser user)
{
Save(_session, user);
}
public void SaveUser(ISession session, IUser user)
{
session.Save(user);
}
III. Don't use the existing services. Have the PostService do it's own thing, even if there is a bit of duplication (e.g. getting user details etc.)
IV. Remove the ISession from the services' constructors, and pass it in to each method (and deal with the Controllers' accordingly.
V. Something else.
I guess I'm leaning towards the first one, but I'm not sure where PostService would live. If it goes in Proj.Services.NH, then I'd have to introduce a dependency on System.Web.Mvc or SignalR, which I don't want to do. If it lives in Proj.Web, then I'd have to introduce a dependency on NHibernate, which I also don't want to do. It doesn't belong in Proj.Infrastructure, as it is application code. Should it have it's own project with dependencies on everything, or is there a better way?
I would use some sort of auto factory for the additional services you need. So you would write your PostService constructor as:
public PostService( Func<INeededService1> factory1,Func<INeededService2> factory2 ...)
{
...
}
and then use this extension to have these factory automatically working ( by querying the container ).
I am brand new to IoC and thus have been following the examples provided by Jeffery Palermo in his posts at http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ and in his book hosted here https://github.com/jeffreypalermo/mvc2inaction/tree/master/manuscript/Chapter23
Most important to note is that I am not using a pre-rolled IoC container, mostly because I want to understand all the moving parts.
However, I am creating a windows service rather than an ASP.NET MVC webapp so I am little bogged down on the startup portion. Specifically, in the web.config he registers an IHttpModule implementation INSIDE the infrastructure project as the startup module and then uses a post-build event to copy the necessary dlls into the website directory to get around having a direct dependency in the web project itself.
I don't think I have this type of luxury in a true windows service, so how do I achieve something similar, should I have a small startup project which has dependencies to both the Infrastructure and Core, or is there another method to get around the compile-time restrictions of the windows service?
Thanks in advance.
Based on the tags of this question (c#) I'm assuming that you'll implement the Windows Service by deriving from ServiceBase. If so, the OnStart method will be your Composition Root - this is where you compose the application's object graph. After you've composed the object graph, composition is over and the composed object graph takes over.
In OnStop you can decommission the object graph again.
There's nothing stopping you from implementing the various components of the resolved object graph in separate assemblies. That's what I would do.
I think you missunderstood the role of an IoC framework.
To answer your question
but doesn't the reference imply dependency?
Yes it does, but on an other level. IoC is about dependencies between classes.
Instead of using new Something() in your class you provide a constructor which requires all dependent interfaces. This way the class has no control which implementation is passed to it. This is inversion of control. The IoC Container is just an aid to help managing the dependencies in a nice manner.
Say you have a ICustomerNotificationService interface with an implementation like
public class MailNotificationService : INotificationService
{
IMailerService _mailer;
ICustomerRepository _customerRepo;
IOrderRepository _orderRepo;
public MailNotificationService(IMailerService mailer,
ICustomerRepository customerRepo,
IOrderRepository oderRepo)
{
// set fields...
}
public void Notify(int customerId, int productId)
{
// load customer and order, format mail and send.
}
}
So if your application requests an instance of ICustomerNotificationServcie the container figures out which concrete implementations to take and tries to satisfy all dependencies the requested class has.
The advantage is that you can easily configure all dependencies in your bootstrapping logic and be able to change the behaviour of your application very easily.
For example when testing you start the application with an IMailerService implementation which writes the mails to a file and in production mode a real mail service is wired. This would not be possible if you newed up say a MailerService in your constructor instead of taking it as a parameter.
A good IoC container can handle much more, for you like lifetime management, singletons, scanning assemblies for Types you want to register and many more. We based our entire plugin system on Structure Map for example.
You may want to take a look at this blog article and its second part.