I am working in a project that has two main parts: a class library assembly and the main application. Both are using Castle Windsor for IoC and both manually setup their list of of components in code (to aid refactoring and prevent the need for a config file). Currently the main application has code like this:
public static void Main()
{
// Perform library IoC setup
LibraryComponent.Init();
// Perform application IoC setup
IoC.Register<IXyz, Abc>("abc");
// etc, etc, ...
// Start the application code ...
}
However the call to initialise the library doesn't seem like a good solution. What is the best way to setup a class library that uses an IoC container to decouple its internal components?
Edit:
Lusid proposed using a static method on each public component in the library that would in turn make the call to initialise. One possible way to make this a bit nicer would be to use something like PostSharp to do this in an aspect-oriented way. However I was hoping for something a bit more elegant ;-)
Lusid also proposed using the AppDomain.AssemblyLoad event to perform custom steps at load time, however I am really after a way to avoid the client assembly from requiring any setup code.
Thanks!
I'm not sure if I'm understanding exactly the problem you are trying to solve, but my first guess is that you are looking for a way to decouple the need to call the Init method from your main application.
One method I've used in the past is a static constructor on a static class in the class library:
static public class LibraryComponent {
static LibraryComponent() {
Init();
}
}
If you have multiple class libraries, and would like a quick and dirty way of evaluating all of them as they are loaded, here's a (kinda hairy) way:
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
}
static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
IEnumerable<Type> types = args.LoadedAssembly.GetTypes()
.Where(t => typeof(IMyModuleInterface).IsAssignableFrom(t));
foreach (Type t in types)
{
doSomethingWithType(t);
}
}
The Where clause could be anything you want, of course. The code above would find any class deriving from IMyModuleInterface in each assembly that gets loaded into the current AppDomain, and then I can do something with it, whether it be registering dependencies, maintaining an internal list, whatever.
Might not be exactly what you are looking for, but hopefully it helps in some way.
You could have a registration module. Basically LibraryComponent.Init() function takes an IRegistrar to wire everything up.
The IRegistrar could basically have a function Register(Type interface, Type implementation). The implimentor would map that function back to their IOC container.
The downside is that you can't rely on anything specific to the container your using.
Castle Windsor actually has a concept called facilities that are basically just ways of wrapping standardised pieces of configuration. In this model, you would simply add the two facilities to the container and they would do the work.
Of course, this wouldn't really be better than calling a library routine to do the work unless you configured the facilities in a configuration file (consider binsor). If you are really allergic to configuration files, your current solution is probably the best.
Related
I use Autofac extensively. Recently I've gotten interested in tweaking the lifetime scopes when registering items for XUnit testing. Basically I want to register a number of standard components I use as "instance per test" rather than what I normally do for runtime (I've found a useful library on github that defines an instance-per-test lifetime).
One way to do this is to define two separate container builds, one for runtime and one for xunit testing. That would work but it gets increasingly expensive to maintain.
What I'd like to do (I think) is modify the registration pipeline dynamically depending upon the context -- runtime or xunit test -- in which it is being built. In pseudocode:
builder.RegisterType<SomeType>().AsImplementedInterfaces().SingleInstance();
...
void TweakPipeline(...)
{
if( Testing )
{
TypeBeingRegistered.InstancePerTest();
}
else
{
TypeBeingRegistered.SingleInstance();
}
}
Is this something Autofac middleware can do? If not is there another capability in the Autofac API which could address it? As always, links to examples would be appreciated.
This is an interesting question. I like that you started thinking about some of the new features in Autofac, very few do. So, kudos for the good question.
If you think about the middleware, yes, you can probably use it to muck with lifetime scope, but we didn't really make "change the lifetime scope on the fly" something easy to do and... I'll be honest, I'm not sure how you'd do it.
However, I think there are a couple of different options you have to make life easier. In the order in which I'd do them if it was me...
Option 1: Container Per Test
This is actually what I do for my tests. I don't share a container across multiple tests, I actually make building the container part of the test setup. For Xunit, that means I put it in the constructor of the test class.
Why? A couple reasons:
State is a problem. I don't want test ordering or state on singletons in the container to make my tests fragile.
I want to test what I deploy. I don't want something to test out OK only to find that it worked because of something I set up in the container special for testing. Obvious exceptions for mocks and things to make the tests actually unit tests.
If the problem is that the container takes too long to set up and is slowing the tests down, I'd probably troubleshoot that. I usually find the cause of this to be either that I'm assembly scanning and registering way, way too much (oops, forgot the Where statement to filter things down) or I've started trying to "multi-purpose" the container to start orchestrating my app startup logic by registering code to auto-execute on container build (which is easy to do... but don't forget the container isn't your app startup logic, so maybe separate that out).
Container per test really is the easiest, most isolated way to go and requires no special effort.
Option 2: Modules
Modules are a nice way to encapsulate sets of registrations and can be a good way to take parameters like this. In this case, I might do something like this for the module:
public class MyModule : Module
{
public bool Testing { get; set; }
protected override void Load(ContainerBuilder builder)
{
var toUpdate = new List<IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle>>();
toUpdate.Add(builder.RegisterType<SomeType>());
toUpdate.Add(builder.RegisterType<OtherType>());
foreach(var reg in toUpdate)
{
if(this.Testing)
{
reg.InstancePerTest();
}
else
{
reg.SingleInstance();
}
}
}
}
Then you could register it:
var module = new MyModule { Testing = true };
builder.RegisterModule(module);
That makes the list of registrations easier to tweak (foreach loop) and also keeps the "things that need changing based on testing" isolated to a module.
Granted, it could get a little complex in there if you have lambdas and all sorts of other registrations in there, but that's the gist.
Option 3: Builder Properties
The ContainerBuilder has a set of properties you can use while building stuff to help avoid having to deal with environment variables but also cart around arbitrary info you can use while setting up the container. You could write an extension method like this:
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle>
EnableTesting<TLimit, TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registration,
ContainerBuilder builder)
{
if(builder.Properties.TryGetValue("testing", out var testing) && Convert.ToBoolean(testing))
{
registration.InstancePerTest();
}
return registration;
}
Then when you register things that need to be tweaked, you could do it like this:
var builder = new ContainerBuilder();
// Set this in your tests, not in production
// builder.Properties["testing"] = true;
builder.RegisterType<Handler>()
.SingleInstance()
.EnableTesting(builder);
var container = builder.Build();
You might be able to clean that up a bit, but again, that's the general idea.
You might ask why use the builder as the mechanism to transport properties if you have to pass it in anyway.
Fluent syntax: Due to the way registrations work, they're all extension methods on the registration, not on the builder. The registration is a self-contained thing that doesn't have a reference to the builder (you can create a registration object entirely without a builder).
Internal callbacks: The internals on how registration works basically boil down to having a list of Action executed where the registrations have all the variables set up in a closure. It's not a function where we can pass stuff in during build; it's self-contained. (That might be interesting to change, now I think of it, but that's another discussion!)
You can isolate it: You could put this into a module or anywhere else and you won't be adding any new dependencies or logic. The thing carting around the variable will be the builder itself, which is always present.
Like I said, you could potentially make this better based on your own needs.
Recommendation: Container Per Test
I'll wrap up by just again recommending container per test. It's so simple, it requires no extra work, there are no surprises, and it "just works."
I am developing a modular WPF application with Prism in .Net Core 5.0 (using MVVM, DryIoc) and I would like to have a module that is not a WPF module, i.e., a module with functionality that can be used by any other module. I don't want any project reference, because I want to keep the loosely coupled idea of the modules.
My first question is: is it conceptually correct? Or is it mandatory that a module has a screen? I guess it should be ok.
The second and more important (for me) is, what would be the best way to create the instance?
This is the project (I know I should review the names in this project):
HotfixSearcher is the main class, the one I need to get instantiated. In this class, for example, I subscribe to some events.
And this is the class that implements the IModule interface (the module class):
namespace SearchHotfix.Library
{
public class HotfixSearcherModule : IModule
{
public HotfixSearcherModule()
{
}
public void OnInitialized(IContainerProvider containerProvider)
{
//Create Searcher instance
var searcher = containerProvider.Resolve<IHotfixSearcher>();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IHotfixSearcher, HotfixSearcher>();
}
}
}
That is the only way I found to get the class instantiated, but I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
For modules that have screens, the instances get created when navigating to them using the RequestNavigate method:
_regionManager.RequestNavigate(RegionNames.ContentRegion, "ContentView");
But since this is only a library with no screens, I can't find any other way to get this instantiated.
According to Prism documentation, subscribing to an event shoud be enough but I tried doing that from within my main class HotfixSearcher but it does not work (breakpoints on constructor or on the event handler of the event to which I subscribe are never hit).
When I do this way, instead, the instance is created, I hit the constructor breakpoint, and obviously the instance is subscribed to the event since it is done in the constructor.
To sum up, is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
Thanks in advance!
Or is it mandatory that a module has a screen?
No, of course not, modules have nothing to do with views or view models. They are just a set of registrations with the container.
what would be the best way to create the instance?
Let the container do the work. Normally, you have (at least) one assembly that only contains public interfaces (and the associated enums), but no modules. You reference that from the module and register the module's implementations of the relevant interfaces withing the module's Initialize method. Some other module (or the main app) can then have classes that get the interfaces as constructor parameters, and the container will resolve (i.e. create) the concrete types registered in the module, although they are internal or even private and completely unknown outside the module.
This is as loose a coupling as it gets if you don't want to sacrifice strong typing.
is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
You can skip the var searcher = part :-) But if the HotfixSearcher is never injected anywhere, it won't be created unless you do it yourself. OnInitialized is the perfect spot for this, because it runs after all modules had their chance to RegisterTypes so all dependencies should be registered.
If HotfixSearcher is not meant to be injected, you can also drop IHotfixSearcher and resolve HotfixSearcher directly:
public void OnInitialized(IContainerProvider containerProvider)
{
containerProvider.Resolve<HotfixSearcher>();
}
I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
It is used, I suppose, although not through calling one of its methods. It's used by sending it an event. That's just fine. Think of it like Task.Run - it's fine for the task to exist in seeming isolation, too.
I have a WPF application based on MVVM with Caliburn.Micro and Ninject. I have a root viewmodel called ShellViewModel. It has a couple of dependencies (injected via constructor) which are configured in Caliburn's Bootstrapper. So far so good.
Somewhere down the line, there is a MenuViewModel with a couple of buttons, that in turn open other viewmodels with their own dependencies. These viewmodels are not created during creation of the root object, but I still want to inject dependencies into them from my IoC container.
I've read this question on service locator vs dependency injection and I understand the points being made.
I'm under the impression however that my MenuViewModel needs to be able to access my IoC container in order the properly inject the viewmodels that are being made dynamically..which is something I'm trying to avoid. Is there another way?
Yes, I believe you can do something a bit better.
Consider that if there was no on-demand requirement then obviously you could make those viewmodels be dependencies of MenuViewModel and so on up the chain until you get to the root of the object graph (the ShellViewModel) and the container would wire everything up.
You can put a "firewall" in the object graph by substituting something that can construct the dependencies of MenuViewModel for the dependencies themselves. The container is the obvious choice for this job, and IMHO from a practical standpoint this is a good enough solution even if it's not as pure.
But you can also substitute a special-purpose factory instead of the container; this factory would take a dependency on the container and provide read-only properties for the real dependencies of MenuViewModel. Accessing the properties would result in having the container resolve the objects and returning them (accessor methods would also work instead of properties; what's more appropriate is another discussion entirely, so just use whatever you think is better).
It may look like that you haven't really changed the status quo, but the situation is not the same it would be if MenuViewModel took a direct dependency on the container. In that case you would have no idea what the real dependencies of MenuViewModel are by looking at its public interface, while now you would see that there's a dependency on something like
interface IMenuViewModelDependencyFactory
{
public RealDependencyA { get; }
public RealDependencyB { get; }
}
which is much more informative. And if you look at the public interface of the concrete MenuViewModelDependencyFactory things are also much better:
class MenuViewModelDependencyFactory : IMenuViewModelDependencyFactory
{
private Container container;
public MenuViewModelDependencyFactory(Container container) { ... }
public RealDependencyA { get { ... } }
public RealDependencyB { get { ... } }
}
There should be no confusion over what MenuViewModelDependencyFactory intends to do with the container here because it's so very highly specialized.
I'm working with the MVVM pattern + a simple ServiceLocator implementation, now to my problem how am I supposed to setup the services when the views are running in design time?
Iv tried this but it does not seem to work in VS 2010 or some thing, I know it worked on my old computer but on my new it does not. so does any one know a good alternative?
Edit: (On behalf of Merlyn Morgan-Graham)
Well what I'm trying to do is this, I have my view, ViewModel and services now the difference here is that I have 2 implementations of each service one for design time and one for run time.
for a better explanation look here.
If you want to decouple your view from your viewmodel, and your viewmodel from your model/dal (basically, if you want to use MVVM), then your view model and data model shouldn't know anything about design time. Design time only applies to the view.
This article shows a way to define your design time data via XML/XAML, so your code underneath doesn't have to know anything about it:
http://karlshifflett.wordpress.com/2009/10/21/visual-studio-2010-beta2-sample-data-project-templates/
After Edit: It turns out that you'll still have to use your view model for your existing XAML bindings to work. This will just populate the view model rather than having to create a new data model. I'm not sure, but there might be classes that allow you to use the WPF binding mechanism to take care of this... Views?
Resume Before Edit...:
As far as the solution in the article you linked first, the designer doesn't instantiate anything but your class, and the code it references. That means that assembly attributes won't be instantiated unless your view code somehow directly references them.
If you really want to couple your view models to your views during design time, and make it so that design time services are registered, then you have to place the service registration code in your view class, or a class the view class directly references.
To do that, you could use static constructors of your views to register your design time services. You could also write a static method on some other class (application?) to (conditionally) register the design time services. Then, call that method in the constructor of your views.
Or you could simply register them in the constructor for each of your views.
Basically, what you want to do is possible, but that method linked in the first article isn't. If you read farther in the comments, you'll see that his method is broken.
You may also want to question the idea of hooking your view model to your view during design time, because the MVVM pattern was made to avoid that sort of thing.
You usually don't need to access services at design-time... Typically, you don't even use your real ViewModels at design-time, you use dummy design data, as explained here. If you really need to use your real ViewModels, you can implement dummy versions of your services, and use them instead of the real services :
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
{
// Design time
ServiceLocator.Instance.Register<IService1>(new DummyService1());
ServiceLocator.Instance.Register<IService2>(new DummyService2());
}
else
{
// Run time
ServiceLocator.Instance.Register<IService1>(new RealService1());
ServiceLocator.Instance.Register<IService2>(new RealService2());
}
Also I do agree to all who have concerns regarding the use of the service locator at design time, I do believe that this is a valid scenario in some use cases.
This is not a discussion on why/why not, this is simple the way it (almost) worked for me.
There is still a problem which I did not solve yet: this only works for one view at a time.
Create a simple bootstrapper for setting up your IoC of choice. Notice the ISupportInitialize interface.
public class Bootstrapper: ISupportInitialize
{
#region ISupportInitialize Members
public void BeginInit() { }
public void EndInit()
{
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
Setup();
}
#endregion
public static void Setup() { SetupServiceLocator(); }
static void SetupServiceLocator()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ConfigService>().As<IConfigService>().ExternallyOwned().SingleInstance();
IContainer container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
}
}
Use the Bootstrapper as before for runtime mode, e.g.:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Bootstrapper.Setup();
}
}
Additionally you need to add it to the application resources for design mode support:
<Application x:Class="MonitoringConfigurator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyBootstrapperNamespace"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:Bootstrapper x:Key="Bootstrapper" />
</Application.Resources>
</Application>
I am new to OSGi and came across several examples about OSGi services.
For example:
import org.osgi.framework.*;
import org.osgi.service.log.*;
public class MyActivator implements BundleActivator {
public void start(BundleContext context) throws Exception {
ServiceReference logRef =
context.getServiceReference(LogService.class.getName());
}
}
My question is, why do you use
getServiceReference(LogService.class.getName())
instead of
getServiceReference("LogService")
If you use LogService.class.getName() you have to import the Interface. This also means that you have to import the package org.osgi.services.log in your MANIFEST.MF.
Isn't that completely counterproductive if you want to reduce dependencies to push loose coupling? As far as I know one advantage of services is that the service consumer doesn't have to know the service publisher. But if you have to import one specific Interface you clearly have to know who's providing it. By only using a string like "LogService" you would not have to know that the Interface is provided by org.osgi.services.log.LogService.
What am I missing here?
Looks like you've confused implementation and interface
Using the actual interface for the name (and importing the interface , which you'll end up doing anyway) reenforces the interface contract that services are designed around. You don't care about the implemenation of a LogService but you do care about the interface. Every LogService will need to implement the same interface, hence your use of the interface to get the service. For all you know the LogService is really a wrapper around SLF4J provided by some other bundle. All you see is the interface. That's the loose coupling you're looking for. You don't have to ship the interface with every implementation. Leave the interface it's own bundle and have multiple implementations of that interface.
Side note: ServiceTracker is usually easier to use, give it a try!
Added benefits: Using the interface get the class name avoids spelling mistakes, excessive string literals, and makes refactoring much easier.
After you've gotten the ServiceReference, your next couple lines will likely involve this:
Object logSvc = content.getService(logRef)
// What can you do with logSvc now?!? It's an object, mostly useless
// Cast to the interface ... YES! Now you need to import it!
LogSerivce logger = (LogService)logSvc;
logger.log(LogService.LOG_INFO, "Interfaces are a contract between implementation and consumer/user");
If you use the LogService, you're coupled to it anyway. If you write middleware you likely get the name parameterized through some XML file or via an API. And yes, "LogService" will fail terribly, you need to use the fully qualified name: "org.osgi.service.log.LogService". Main reason to use the LogService.class.getName() pattern is to get correct renaming when you refactor your code and minimize spelling errors. The next OSGi API will very likely have:
ServiceReference<S> getServiceReference(Class<S> type)
calls to increase type safety.
Anyway, I would never use these low level API unless you develop middleware. If you actually depend on a concrete class DS is infinitely simpler, and even more when you use it with the bnd annotations (http://enroute.osgi.org/doc/217-ds.html).
#Component
class Xyz implements SomeService {
LogService log;
#Reference
void setLog( LogService log) { this.log = log; }
public void foo() { ... someservice ... }
}
If you develop middleware you get the service classes usually without knowing the actual class, via a string or class object. The OSGi API based on strings is used in those cases because it allows us to be more lazy by not creating a class loader until the last moment in time. I think the biggest mistake we made in OSGi 12 years ago is not to include the DS concepts in the core ... :-(
You cannot use value "LogService"
as a class name to get ServiceReference, because you have to use fully qualified class name
"org.osgi.services.log.LogService".
If you import package this way:
org.osgi.services.log;resolution:=optional
and you use ServiceTracker to track services in BundleActivator.start() method I suggest to use "org.osgi.services.log.LogService" instead of LogService.class.getName() on ServiceTracker initializazion. In this case you'll not get NoClassDefFoundError/ClassNotFountException on bundle start.
As basszero mentioned you should consider to use ServiceTracker. It is fairly easy to use and also supports a much better programming pattern. You must never assume that a ServiceReference you got sometime in the past is still valid. The service the ServiceReference points to might have gone away. The ServiceTracker will automatically notify you when a service is registered or unregistered.