I am developing a Windows Service to do some periodical operations, can I use Unity to inject my classes from another library there?
I want to use with the [Dependency] attribute on my services, registering the components on the entry point of the windows service start.
Example:
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
UnityConfig.RegisterComponents();
ServicesToRun = new ServiceBase[]
{
new EventChecker()
};
ServiceBase.Run(ServicesToRun);
}
}
public static class UnityConfig
{
public static void RegisterComponents()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IEventBL, EventBL>();
}
}
public partial class EventChecker : ServiceBase
{
private Logger LOG = LogManager.GetCurrentClassLogger();
[Dependency]
public Lazy<IEventBL> EventBL { get; set; }
protected override void OnStart(string[] args)
{
var events = EventBL.Value.PendingExecution(1);
}
}
In this scenario the EventBL is always null, so is not resolved by the [Dependency] of unity. There aren't a way to make it working?
Thanks!
Solution Found:
After write the answer I found a possible solution, calling to build up method of the container to create the service class works:
UnityContainer container = new UnityContainer();
UnityConfig.RegisterComponents(container);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
container.BuildUp(new EventChecker())
};
ServiceBase.Run(ServicesToRun);
If you know any other solution, please share it :)
A DI Container like Unity can just as well be used to compose the object graphs of Windows Services. Note that in general you should prefer using constructor injection. This prevents temporal coupling and prevents your code to have a dependency on the DI library itself (which is quite ironic to have need dependency on the DI library, since it's trying to help you preventing strong coupling between components).
Furthermore, you should simply let the container resolve your services. In other words, don't new up your services by hand, but request a new instance from the container:
ServicesToRun = new ServiceBase[]
{
container.Resolve<EventChecker>()
};
But do note that your EventChecker is resolved once and stored for the duration of the application. That effectively makes it a singleton and with that all its dependencies will becomes singletons. So instead, it's better to make your ServiceBase implementation part of the composition root and resolve new instances from the container every time your time fires:
public class EventChecker : ServiceBase
{
private static IUnityContainer container;
public EventChecker(IUnityContainer container)
{
this.container = container;
}
public void SomeOperationThatGetsTriggeredByATimer()
{
using (var scope = this.container.BeginLifetimeScope())
{
var service = scope.Resolve<IEventCheckerService>();
service.Process();
}
}
}
Related
I was looking into "Dependency Injection" on xamarin forms and found some concepts that use something like ContainerBuilder. The solutions found online such as this, talk about how you can have DI setup and inject them into your view models. However, personally, I didn't find this or the whole concept of view models and binding very tidy for several reasons. I would rather create services that can be reused by the business logic, which seems to make the code a lot cleaner. I felt that implementing an IServiceProvider would result in a much cleaner implementation. I was planning on implementing a service provider something like this:
IServiceProvider Provider = new ServiceCollection()
.AddSingleton<OtherClass>()
.AddSingleton<MyClass>()
.BuildServiceProvider();
Firstly, I am not sure why there are no xamarin examples of these. So, I am not sure if there is anything wrong with going towards this direction. I have looked into ServiceCollection class. The package it is from, Microsoft.Extensions.DependencyInjection, doesn't have "aspnetcore" in its name. It, however, has its owner as "aspnet". I am not entirely sure if ServiceCollection is only meant for web applications or it would make sense to use it for mobile apps.
Is it safe to use IServiceProvider with ServiceCollection as long as I use all singletons? is there any concern (in terms of performance or ram) I am missing?
Update
After the comments from Nkosi, I have taken another look at the link and noticed a couple of things:
The documentation link is dated around the same time Microsoft.Extensions.DependencyInjection was still in beta
All points in the list under "several advantages to using a dependency injection container" in the documentation also apply to DependencyInjection as far as I can see.
Autofac process seems to revolve around ViewModels which I am trying to avoid using.
Update 2
I managed to get DI directly into the behind code of pages with the help of a navigation function something like this:
public static async Task<TPage> NavigateAsync<TPage>()
where TPage : Page
{
var scope = Provider.CreateScope();
var scopeProvider = scope.ServiceProvider;
var page = scopeProvider.GetService<TPage>();
if (navigation != null) await navigation.PushAsync(page);
return page;
}
This implementation uses Splat and some helper/wrapper classes to conveniently access the container.
The way how the services are registered is a bit verbose but it could cover all uses cases I have encountered so far; and the life cycle can be changed quite easily as well, e.g. switching to a lazy creation of a service.
Simply use the ServiceProvider class to retrieve any instances from the IoC container anywhere in your code.
Registering of your Services
public partial class App : Application
{
public App()
{
InitializeComponent();
SetupBootstrapper(Locator.CurrentMutable);
MainPage = new MainPage();
}
private void SetupBootstrapper(IMutableDependencyResolver resolver)
{
resolver.RegisterConstant(new Service(), typeof(IService));
resolver.RegisterLazySingleton(() => new LazyService(), typeof(ILazyService));
resolver.RegisterLazySingleton(() => new LazyServiceWithDI(
ServiceProvider.Get<IService>()), typeof(ILazyServiceWithDI));
// and so on ....
}
Usage of ServiceProvider
// get a new service instance with every call
var brandNewService = ServiceProvider.Get<IService>();
// get a deferred created singleton
var sameOldService = ServiceProvider.Get<ILazyService>();
// get a service which uses DI in its contructor
var another service = ServiceProvider.Get<ILazyServiceWithDI>();
Implementation of ServiceProvider
public static class ServiceProvider
{
public static T Get<T>(string contract = null)
{
T service = Locator.Current.GetService<T>(contract);
if (service == null) throw new Exception($"IoC returned null for type '{typeof(T).Name}'.");
return service;
}
public static IEnumerable<T> GetAll<T>(string contract = null)
{
bool IsEmpty(IEnumerable<T> collection)
{
return collection is null || !collection.Any();
}
IEnumerable<T> services = Locator.Current.GetServices<T>(contract).ToList();
if (IsEmpty(services)) throw new Exception($"IoC returned null or empty collection for type '{typeof(T).Name}'.");
return services;
}
}
Here is my csproj file. Nothing special, the only nuget package I added was Spat
Shared Project csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Splat" Version="9.3.11" />
<PackageReference Include="Xamarin.Forms" Version="4.3.0.908675" />
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
</ItemGroup>
</Project>
I know the question has been asked 2 years ago, but I might have a solution that could match what you are asking for.
In the past few months I've been working on apps using Xamarin and WPF and I used the Microsoft.Extensions.DependencyInjection package to add constructor dependency injection to my view models, just like an ASP.NET Controller. Which means that I could have something like:
public class MainViewModel : ViewModelBase
{
private readonly INavigationService _navigationService;
private readonly ILocalDatabase _database;
public MainViewModel(INavigationService navigationService, ILocalDatabase database)
{
_navigationService = navigationService;
_database = database;
}
}
To implement this kind of process I use the IServiceCollection to add the services and the IServiceProvider to retrieve the registered services.
What is important to remember, is that the IServiceCollection is the container where you will register your dependencies. Then when building this container, you will obtain a IServiceProvider that will allow you to retrieve a service.
To do so, I usually create a Bootstrapper class that will configure the services and initialize the main page of the application.
The basic implementation
This example show how to inject dependencies into a Xamarin page. The process remains the same for any other class. (ViewModels or other classes)
Create a simple class named Bootstrapper in your project and intitialize a IServiceCollection and IServiceProvider private fields.
public class Bootstrapper
{
private readonly Application _app;
private IServiceCollection _services;
private IServiceProvider _serviceProvider;
public Bootstrapper(Application app)
{
_app = app;
}
public void Start()
{
ConfigureServices();
}
private void ConfigureServices()
{
_services = new ServiceCollection();
// TODO: add services here
_serviceProvider = _services.BuildServiceProvider();
}
}
Here in the ConfigureServices() method we just create a new ServiceCollection where we are going to add our services. (See https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollection?view=dotnet-plat-ext-3.1)
Once our services have been added, we build the service provider that will allow us to retrieve the previously registered services.
Then in your App class constructor, create a new Bootstrapper instance and call the start method to initialize the application.
public partial class App : Application
{
public App()
{
InitializeComponent();
var bootstrapper = new Bootstrapper(this);
bootstrapper.Start();
}
...
}
With this piece of code, you have setup your service container, but we still need to initialize the MainPage of the application. Go back to the bootstrapper's Start() method and create a new instance of the wanted main page.
public class Bootstrapper
{
...
public void Start()
{
ConfigureServices();
// Real magic happens here
var mainPageInstance = ActivatorUtilities.CreateInstance<MainPage>(_serviceProvider);
_app.MainPage = new NavigationPage(mainPageInstance);
}
}
Here we use the ActivatorUtilities.CreateInstance<TInstance>() method to create a new MainPage instance. We give the _serviceProvider as parameter, because the ActivatorUtilities.CreateInstance() method will take care of creating your instance and inject the required services into your object.
Note that this is what ASP.NET Core using to instanciate the controllers with contructor dependency injection.
To test this, create a simple service and try to inject it into your MainPage contructor:
public interface IMySimpleService
{
void WriteMessage(string message);
}
public class MySimpleService : IMySimpleService
{
public void WriteMessage(string message)
{
Debug.WriteLine(message);
}
}
Then register it inside the ConfigureServices() method of the Bootstrapper class:
private void ConfigureServices()
{
_services = new ServiceCollection();
_services.AddSingleton<IMySimpleService, MySimpleService>();
_serviceProvider = _services.BuildServiceProvider();
}
And finally, go to your MainPage.xaml.cs, inject the IMySimpleService and call the WriteMessage() method.
public partial class MainPage : ContentPage
{
public MainPage(IMySimpleService mySimpleService)
{
mySimpleService.WriteMessage("Hello world!");
}
}
There you go, you have successfully registered a service and injected it into your page.
The real magic with constructor injection really occurs using the ActivatorUtilities.CreateInstance<T>() method by passing a service provider. The method will actually check the parameters of your constructor and try to resolve the dependencies by trying to get them from the IServiceProvider you gave him.
Bonus : Register platform specific services
Well this is great right? You are able to inject services into any classes thanks to the ActivatorUtilities.CreateInstance<T>() method, but sometimes you will also need to register some platform specific services (Android or iOS).
With the previous method is not possible to register platform-specific services, because the IServiceCollection is initialized in the Bootstrapper class. No worries, the workaround is really simple.
You just need to extract the IServiceCollection initialization to the platform-specific code. Simply initialize the service collection on the MainActivity.cs of your Android project and in the AppDelegate of your iOS project and pass it to your App class that will forward it to the Bootstrapper:
MainActivity.cs (Android)
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
...
var serviceCollection = new ServiceCollection();
// TODO: add platform specific services here.
var application = new App(serviceCollection);
LoadApplication(application);
}
...
}
AppDelegate.cs (iOS)
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
var serviceCollection = new ServiceCollection();
// TODO: add platform specific services here.
var application = new App(serviceCollection);
LoadApplication(application);
return base.FinishedLaunching(app, options);
}
}
App.xaml.cs (Common)
public partial class App : Application
{
public App(IServiceCollection services)
{
InitializeComponent();
var bootstrapper = new Bootstrapper(this, services);
bootstrapper.Start();
}
...
}
Bootstrapper.cs (Common)
public class Bootstrapper
{
private readonly Application _app;
private readonly IServiceCollection _services;
private IServiceProvider _serviceProvider;
public Bootstrapper(Application app, IServiceCollection services)
{
_app = app;
_services = services;
}
public void Start()
{
ConfigureServices();
var mainPageInstance = ActivatorUtilities.CreateInstance<MainPage>(_serviceProvider);
_app.MainPage = new NavigationPage(mainPageInstance);
}
private void ConfigureServices()
{
// TODO: add services here.
_serviceCollection.AddSingleton<IMySimpleService, MySimpleService>();
_serviceProvider = _services.BuildServiceProvider();
}
}
And that's all, you are now able to register platform-specific services and inject the interface into your pages / view models / classes easily.
I wish to inject a service into a custom class i have created> i have been using Dependency injection to inject the same service into my WebApi controllers but cannot seem to understand why it doesn't work in my "InputDataValidationModel" class
This is what i am trying to do:
public class InputDataValidationModel
{
private ISec300_EE_SubmissionRepository _service { get; set; }
public InputDataValidationModel(ISec300_EE_SubmissionRepository service)
{
_service = service;
}
}
In the Global.asax i registered the types as follow:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
// Register the Controllers that should be injectable
unity.RegisterType<SEC300_EE_SubmissionController>();
unity.RegisterType<InputDataValidationModel>();
unity.RegisterType<ISec300_EE_SubmissionRepository, Sec300_EE_SubmissionRepository>(new ContainerControlledLifetimeManager());
unity.RegisterType<IClientRepository, ClientRepository>(new ContainerControlledLifetimeManager());
// Finally, override the default dependency resolver with Unity
config.DependencyResolver = new IoCContainer(unity);
}
What I cant understand specifically is that this works perfectly when done in my controller below:
public class SEC300_EE_SubmissionController : ApiController
{
private ISec300_EE_SubmissionRepository _service;
public SEC300_EE_SubmissionController(ISec300_EE_SubmissionRepository service)
{
if (service == null)
{
throw new ArgumentNullException("service");
}
_service = service;
}
}
It does not work because controllers are instantiated by Web API, and when Web API creates a controller it calls BeginScope which is the entry point to call your IoC and proceeds to resolve and constructs objects for you.
In your case InputDataValidationModel is not used and may be for this reason you don't have the instance
update
Do you perhaps have any suggestions on how i would inject my service into InputDataValidationModel ?
Option 1
You can use IDependencyResolver take a look at this link Dependency Resolution with the Unity Container`'
And after this you can resolve your service like this
var instance =GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (InputDataValidationModel));
Option 2
You might use service locator even it is an anti-pattern
static void Main(string[] args)
{
UnityServiceLocator locator = new UnityServiceLocator(ConfigureUnityContainer(
ServiceLocator.SetLocatorProvider(() => locator);
var a = ServiceLocator.Current.GetInstance<IFoo>();
var b = ServiceLocator.Current.GetInstance<IFoo>();
Console.WriteLine(a.Equals(b));
}
private static IUnityContainer ConfigureUnityContainer()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
return container;
}
Hope this help
I'm working on integrating a legacy database with Asp.Net Zero. I created the model classes using EntityFramework Reverse POCO Generator in a separate Models class library project. I also reversed engineered the DbContext into a separate Data class library project. I would like to use the Data Onion framework for my repositories and unit of work. When I use the recommended IOC container Autofaq my Test Winform application works correctly.
However, the Web Project utilizes Castle.Windsor. I'm uncertain on how to do the wire-up.
I'm creating a new container called ClientDesktopContainer:
internal class ClientDesktopContainer : WindsorContainer
{
public ClientDesktopContainer()
{
RegisterComponents();
}
private void RegisterComponents()
{
var connectionstring = ConfigurationManager.ConnectionStrings["MyDbContext"].ConnectionString;
// Data Onion
Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(new DbContextConfig(connectionstring, typeof(MyDbContext), new MigrateToLatestVersion(new Seeder())));
Component.For<IDbContextScope>().ImplementedBy<DbContextScope>();
Component.For<IDbContextScopeFactory>().ImplementedBy<DbContextScopeFactory>();
Component.For<IAmbientDbContextLocator>().ImplementedBy<AmbientDbContextLocator>();
Component.For<IDbContextReadOnlyScope>().ImplementedBy<DbContextReadOnlyScope>();
// Data Onion Unit of Work
Component.For<IRepositoryLocator>().ImplementedBy<RepositoryLocator>();
// Component.For<IRepositoryResolver>().ImplementedBy<CastleWindsorRepositoryResolver>();
Component.For<IUnitOfWorkFactory>().ImplementedBy<UnitOfWorkFactory>();
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>();
Component.For<IReadOnlyUnitOfWork>().ImplementedBy<IReadOnlyUnitOfWork>();
// Custom
Component.For<IRepository<Enrollment>>()
.ImplementedBy<BaseRepository<Enrollment, MyDbContext>>();
}
My application invocation code is Program:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IoC.Initialize(new ClientDesktopContainer());
var dbContextScopeFactor = IoC.Resolve<IDbContextScopeFactory>();
using (var dbReadOnly = dbContextScopeFactor.CreateReadOnly())
{
var context = dbReadOnly.DbContexts.Get<MyDbContext>();
var individuals = context.Enrollments.ToList();
foreach (var individual in individuals)
{
// do stuff
}
}
Application.Run(new ViewMain());
}
}
I created a static IOC:
public static class IoC
{
private static IWindsorContainer _container;
public static void Initialize(IWindsorContainer container)
{
_container = container;
}
public static T Resolve<T>()
{
try
{
return _container.Resolve<T>();
}
catch
{
throw;
}
}
}
The Data Onion documentation mentions registering a custom Resolver for IRepositoryResolver.
I created a CastleWindsorRepositoryResolver:
public class CastleWindsorRepositoryResolver : IRepositoryResolver
{
public IRepository<TEntity> Resolve<TEntity>() where TEntity : class
{
// TODO: Resolve wire-up goes here
throw new System.NotImplementedException();
}
}
I'm receiving a ComponentNotFoundExpection:
Updated to fix constructor parameter for DbContextFactory (to RegisterComponents method):
var dbContextConfig = new DbContextConfig[]
{
new DbContextConfig(
connectionString,
typeof(MyDbContext),
new MigrateToLatestVersion(new Seeder())
)
};
// Data Onion
Register(Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(Dependency.OnValue<DbContextConfig[]>(dbContextConfig)));
Add call to Register in:
internal class ClientDesktopContainer : WindsorContainer
{
public ClientDesktopContainer()
{
RegisterComponents();
}
private void RegisterComponents()
{
var connectionstring = ConfigurationManager.ConnectionStrings["MyDbContext"].ConnectionString;
/* HERE CALL TO REGISTER: */
this.Register(
// Data Onion
Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(new DbContextConfig(connectionstring, typeof(MyDbContext), new MigrateToLatestVersion(new Seeder()))),
Component.For<IDbContextScope>().ImplementedBy<DbContextScope>(),
Component.For<IDbContextScopeFactory>().ImplementedBy<DbContextScopeFactory>(),
Component.For<IAmbientDbContextLocator>().ImplementedBy<AmbientDbContextLocator>(),
Component.For<IDbContextReadOnlyScope>().ImplementedBy<DbContextReadOnlyScope>(),
// Data Onion Unit of Work
Component.For<IRepositoryLocator>().ImplementedBy<RepositoryLocator>(),
// Component.For<IRepositoryResolver>().ImplementedBy<CastleWindsorRepositoryResolver>(),
Component.For<IUnitOfWorkFactory>().ImplementedBy<UnitOfWorkFactory>(),
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>(),
Component.For<IReadOnlyUnitOfWork>().ImplementedBy<IReadOnlyUnitOfWork>(),
// Custom
Component.For<IRepository<Enrollment>>()
.ImplementedBy<BaseRepository<Enrollment, MyDbContext>>() );
}
Without Register you are just creating registration object without actually putting types in container. Another thing that may help, by default Castle will register components as singletons add LifestyleTranscient or PerWebRequest to your UnitOfWork registrations.
I am creating a Windows Service which uses existing class library for application and domain models.
Application layer already have already defined ContainerConfig which registers all Interfaces like
public class ConfigContainer
{
public UnityContainer ContainerConfig()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IAttachmentService, AttachmentService>(new ContainerControlledLifetimeManager());
container.RegisterType<IBrxxgeService, BrxxgeService>(new ContainerControlledLifetimeManager());
container.RegisterType<ICaxxxxociationService, CaxxxxociationService>(new ContainerControlledLifetimeManager());
container.RegisterType<ITraxxxacityService, TraxxxcityService>(new ContainerControlledLifetimeManager());
return container;
}
}
There are more than 30 Service Interfaces registered here like that. in Window Service Program.cs
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new DClearanceService()
};
ServiceBase.Run(ServicesToRun);
}
Then in DClearanceService.cs
public partial class DClearanceService : ServiceBase
{
private ConfigContainer _containerConfig = new ConfigContainer();
private UnityContainer _container = new UnityContainer();
public DimensionalClearanceService()
{
InitializeComponent();
ExceptionHandlingManager.InitializeExceptionManager();
_container = _containerConfig.ContainerConfig();
}
Inside my methods are resolving container:
public class EMTrocessor
{
_clRequestService = Container.Resolve<IClRequestService>();
public bool ProcessMessage(string message)
{
List<ClOutput> clOutputs = _clRequestService.GetClOutputs();
}
}
If I run this code using visual studio in debugger mode, it works fine but when I run this windows service, I get Microsoft.Practices.Unity.ResolutionFailedException
<Description>An exception of type 'Microsoft.Practices.Unity.ResolutionFailedException' occurred and was caught.</Description>
<DateTime>2015-11-30 16:53:55Z</DateTime>
<ExceptionType>Microsoft.Practices.Unity.ResolutionFailedException, Microsoft.Practices.Unity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f</ExceptionType>
<Message>Resolution of the dependency failed, type = "CPR.Apps.Application.Interfaces.IClEventService", name = "(none)".
Exception occurred while: Calling constructor CPR.Apps.Application.Services.CleranceEventService().
Exception is: ResolutionFailedException - Resolution of the dependency failed, type = "CPR.Apps.Domain.Interfaces.IClEventManager", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, CPR.Apps.Domain.Interfaces.IClEventManager, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:
Resolving CPR.Apps.Domain.Interfaces.IClEventManager,(none)
When I call service, it already resolves the related service and this is how visual studio interact with db and returns the result. Why it can't do the same when I run Windows Service?
My question is:
how do I resolve this issue? Do I need to add
_attachmentService = Container.Resolve<IAttachmentService>();
_brxxgeService = Container.Resolve<IBrxxgeService>();
_clRequestService = Container.Resolve<IClRequestService>();
for all of the interface services here?
if yes, where should I add them?
Please help.
Better way to use continer extensions:
public class ModelContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<IAttachmentService, AttachmentService>(new ContainerControlledLifetimeManager());
Container.RegisterType<IBrxxgeService, BrxxgeService>(new ContainerControlledLifetimeManager());
Container.RegisterType<ICaxxxxociationService, CaxxxxociationService>(new ContainerControlledLifetimeManager());
Container.RegisterType<ITraxxxacityService, TraxxxcityService>(new ContainerControlledLifetimeManager());
}
}
public partial class DClearanceService : ServiceBase
{
private UnityContainer _container = new UnityContainer();
public DimensionalClearanceService()
{
InitializeComponent();
ExceptionHandlingManager.InitializeExceptionManager();
_container.AddExtension(new ModelContainerExtension());
}
Why it's better? In your case you replace whole container variable, and if you made some registraions before - you'll lose it. With AddExtension you'll add new registrations to existing ones.
I have a Windows service where I use OWIN and NancyFX to host a website on top of it. On many places in my service, I use Unity to inject dependencies into classes, mostly services. However, if I use them in any Nancy modules, the dependencies get resolved twice because Nancy uses its own IoC container (TinyIoC).
Fortunately, Nancy allows to override the default IoC container generation and use of an existing one by creating a nancy bootstrapper. But how do I pass my existing IUnityContainer to the bootstrapper?
Basically, all I have to start OWIN is...
WebApp.Start<MyOwinStarter>(url);
How can I pass a Unity container to it to pass it further to the nancy bootstrapper?
#ccellar got me into the right direction.
I created a static class UnityHelper with the following methods:
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => {
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unityConfiguration");
return new UnityContainer().LoadConfiguration(section);
});
public static IUnityContainer GetConfiguredContainer() {
return container.Value;
}
Created a custom NancyBootstrapper class:
public NancyBootstrapper(IUnityContainer container) {
if(container == null)
throw new ArgumentNullException("container");
this._unityContainer = container;
}
protected override IUnityContainer GetApplicationContainer() {
return _unityContainer;
}
and passed the container to the bootstrapper in my web app startup class:
appBuilder.UseNancy(new NancyOptions {
EnableClientCertificates = true,
Bootstrapper
= new NancyBootstrapper(UnityHelper.GetConfiguredContainer())
});
Neat!
Disclaimer: I really don't know if this is the best/cleanest/whatever solution to this problem. But for me it works.
I wrapped my container (Castle Windsor) like this, which is basically a singleton.
public class Container
{
// static holder for instance, need to use lambda to construct since constructor private
private static readonly Lazy<IWindsorContainer> instance = new Lazy<IWindsorContainer>(() =>
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
return container;
});
// private to prevent direct instantiation.
private Container()
{
}
// accessor for instance
public static IWindsorContainer Instance
{
get
{
return instance.Value;
}
}
}
Then in my custom bootstrapper I access the already configured container like this
protected override Castle.Windsor.IWindsorContainer GetApplicationContainer()
{
return Container.Instance;
}
Actually, the easiest and correct way, would be to inherit a new bootstrapper class from the Bootstrapper type you are using - in your case WindsorNancyBootstrapper and override the GetApplicatioContainer method and return your instance
You can read more about it here
https://github.com/NancyFx/Nancy.bootstrappers.windsor#customizing