structuremap port to castle windsor - c#

I am trying to port some structuremap code to castle windor. At the moment, I am getting this error:
No component for supporting the service CreateTestCommandHandler was found
I am using a console app to test things:
Console app:
private static IWindsorContainer _container;
...
static void Main()
{
_container = new WindsorContainer();
ApplicationBootStrapperCastleWindsor.BootStrap(_container);
...
Some more abbreviated code:
public class CreateTestCommandHandler : ICommandHandler<CreateTestCommand>
{
private readonly IDomainRepository<IDomainEvent> _repository;
public CreateTestCommandHandler(IDomainRepository<IDomainEvent> repository)
{
_repository = repository;
}
...
and:
public class ApplicationBootStrapperCastleWindsor
{
public void BootStrapTheApplication(IWindsorContainer container)
{
container.Install(new DomainInstaller());
}
public static void BootStrap(IWindsorContainer container)
{
new ApplicationBootStrapperCastleWindsor().BootStrapTheApplication(container);
}
}
and:
public class DomainInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IDomainRepository<IDomainEvent>>().ImplementedBy<DomainRepository<IDomainEvent>>());
Can someone see anything obvious wrong? Inspecting the container I also get IDomainRepository in potentially reconfigured components.
The original structuremap code is as follows:
ForRequestedType<IDomainRepository<IDomainEvent>>()
.TheDefault.Is.OfConcreteType<DomainRepository<IDomainEvent>>();
PS:
The actual exception is thrown in GetCorrectlyInjectedCommandHandler (original structuremap code can be found here):
public class RegisterCommandHandlersInMessageRouter
{
private static IWindsorContainer _container;
public static void BootStrap(IWindsorContainer container)
{
_container = container;
new RegisterCommandHandlersInMessageRouter().RegisterRoutes(new MessageRouter());
}
private static object GetCorrectlyInjectedCommandHandler(Type commandHandler)
{
return _container.Resolve(commandHandler);
}
}

It seems like you're misunderstanding how Windsor finds your components. You can either register components explicitly (like you did for IDomainRepository<IDomainEvent> in your DomainInstaller), or you can register all types in an assembly (for example) by convention. Either way, if you don't tell Windsor about your type it will throw the exception that you received.
Take a look at registration by convention, it tends to be an easy place to start and can reduce a lot of maintenance moving forward. You can override any auto-registrations by performing manual registrations (again like you did above) if you need to change lifestyles or other properies of specific components.
I don't know much about StructureMap but I see it has similar auto-registration functionality that you may already be using.

Related

Register IMemoryCache with SimpleContainer using Caliburn Micro

I've registered an instance of the IMemoryCache (Microsoft.Extensions.Cachine.Memory 3.1.5) as a singleton with a SimpleContainer for use with Caliburn Micro for a WPF application that I'm writing in .Net Core 3.1.
In my Bootstrapper, I have the following code
public class Bootstrapper : BootstrapperBase
{
private SimpleContainer _container = new SimpleContainer();
public Bootstrapper()
{
Initialize();
}
protected override void Configure()
{
_container.Instance(_container);
_container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>()
.Singleton<IMemoryCache, MemoryCache>();
}
When I come to use the IMemoryCache in a class it throws an Exception as it requires MemoryCacheOptions to be passed into the constructor of the MemoryCache.
I've tried to add MemoryCacheOptions to the Singleton registration but that's not accepted.
This is the constructor of my ReferenceDataHelper class where I'm trying to inject the IMemoryCache, it fails with a System.Reflection.TargetInvocationException when it constructs the ReferenceDataHelper class.
public class ReferenceDataHelper : IReferenceDataHelper
{
private IMemoryCache _memoryCache;
private IReferenceDataHandler _referenceDataHandler;
public ReferenceDataHelper(IReferenceDataHandler referenceDataHandler, IMemoryCache memoryCache)
{
_referenceDataHandler = referenceDataHandler;
_memoryCache = memoryCache;
}
I can't figure out how to set this up - can anyone offer some help?
Thanks!
You could create an instance yourself and then register that instance with the container.
protected override void Configure()
{
_container.Instance(_container);
_container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>()
.Instance<IMemoryCache>(new MemoryCache(new MemoryCacheOptions()));
}
An instance provided to the container is effectively a singleton because the container will only ever provide the instance you gave it. The benefit of providing an instance to the container is you get to control how the object is created.
I think I have found a solution but I'm not sure if this is the best way to solve it.
I have created a wrapper that implement IMemoryCache, in this class I instantiate a new MemoryCache opbject and pass in the MemoryCacheOptions.
public class ReferenceDataMemoryCache : IMemoryCache
{
private MemoryCache memoryCache;
public ReferenceDataMemoryCache()
{
MemoryCacheOptions memoryCacheOptions = new MemoryCacheOptions();
memoryCache = new MemoryCache(memoryCacheOptions);
}
public ICacheEntry CreateEntry(object key)
{
return memoryCache.CreateEntry(key);
}
public void Dispose()
{
memoryCache.Dispose();
}
public void Remove(object key)
{
memoryCache.Remove(key);
}
public bool TryGetValue(object key, out object value)
{
return memoryCache.TryGetValue(key, out value);
}
}
I updated the Bootstrapper to register the singleton with my wrapper class.
protected override void Configure()
{
_container.Instance(_container);
_container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>()
.Singleton<IMemoryCache, MemoryCache>();
}
While this works, if this were a larger class (IMemoryCache has a small number of methods to implement) it feels like a lot of extra work to pass the MemoryCacheOptions to the constructor.
If anyone has thoughts on this approach it would be appreciated.

Unity Extending Dependency Injection Containers

I'm working on a project which currently uses the Service Locator Anti-Pattern all over the code. I'm starting the process to slowly convert everything to using dependency injection, however because of the sheer size of the project I'd like to do this over the course of time.
I'm have a custom factory with 100's of dependencies registered with custom implementations. So I'd like to just wrap my container with unity, if my current container doesn't have the implementation then fall back to use unitys.
I've written this class to wrap IUnityContainer
public class GlobalFactoryUnityWrapper : IUnityContainer
{
IUnityContainer _unityContainer = new UnityContainer();
IUnityContainer _parent;
public GlobalFactoryUnityWrapper(IUnityContainer parent = null)
{
this._parent = parent ?? this._unityContainer.Parent;
}
public IUnityContainer Parent => this._parent;
//... Other IUnityContainer members
public object Resolve(Type type, string name, params ResolverOverride[] resolverOverrides)
{
if(GlobalContext.InstanceFactory.CanGetInstance(type))
{
return GlobalContext.InstanceFactory.GetInstance(type);
}
return this._unityContainer.Resolve(type, name, resolverOverrides);
}
}
I have most of the dependencies register for my controller there, However the controllers themselves are not, So it falls back to use unity's container.
Edit
I think I'm using the wrong thing, I should be using a strategy. my main goal is if the container doesn't contain an implementation, Fall back to use a what's registered in the old container
I needed to create a fallback strategy, this probably isn't the most optimal code but it's working for now
public class FactoryFallbackExtension : UnityContainerExtension
{
public FactoryFallbackExtension()
{
}
protected override void Initialize()
{
var strategy = new FallBackStrategy(Context);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
}
public class FallBackStrategy : BuilderStrategy
{
private ExtensionContext baseContext;
public FallBackStrategy(ExtensionContext baseContext)
{
this.baseContext = baseContext;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface)
{
if(GlobalContext.InstanceFactory.CanGetInstance(key.Type))
context.Existing = GlobalContext.InstanceFactory.GetInstance(key.Type);
}
}
}
Then When I configure my container I can just add the Container extension like so:
public static void Configure()
{
var container = new UnityContainer();
RegisterDepedencies(container);
container.AddExtension(new FactoryFallbackExtension());
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
SetControllerFactory(container);
}

How to access IUnityContainer in non-MVC applications?

I know ASP.NET MVC has DependencyResolver. How to have the similar application-wide access to IUnityContainer in non-MVC applications? Using public static class is nonsense. Here is my use case:
public partial class App : Application
{
public App()
{
IUnityContainer container = new UnityContainer();
container.RegisterInstance(new MyClass());
}
}
public class MainViewModel
{
public MainViewModel()
{
IUnityContainer container = ???
if (container.IsRegistered<MyClass>())
DoSomething();
}
}
If you're looking for a solution that works for most applications you can register the component at the highest level, and then resolve it. As long as you resolve the instance Unity will resolve the dependencies (such as IUnityContainer).
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Registering dependencies ...");
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>();
// Do other registrations.
var program = container.Resolve<ProgramStarter>();
// Since ProgramStarter was resolved using Unity it will also resolve the container.
program.Run();
}
}
public class ProgramStarter
{
public ProgramStarter(IUnityContainer container)
{
// Do something with container.
}
public Run()
{
// Do stuff.
}
}
Or an example for WPF:
IUnityContainer container = new UnityContainer();
// Do registrations.
var window = container.Resolve<MainWindow>();
window.Show();
MainWindow will now be able to resolve both the container and other dependencies.
Also, have a look at this question: Where to place and configure IoC container in a WPF application?
As a sidenote I usually keep my container as a static instance, and seen a lot of other implementations doing the same thing. I find it convenient to be able to use it when you find yourself in a situation when it's not possible to resolve it.
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
// Possibly do registrations here as well...
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
I don't think there is any way other than you specified to implement IOC and DI for non MVC applications. Still if there's a way then any suggestions are appreciated.

Access or get Autofac Container inside a static class

I need to get or access to my IoC container in a static class. This is my (simplified) scenario:
I register dependencies for ASP .net Web Api in a Startup class (but also I do this for MVC or WCF. I have a DependecyResolver project, but for simplicity, consider the following code)
// Web Api project - Startup.cs
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
var builder = new ContainerBuilder();
// ... Omited for clarity
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandle<>))
.AsImplementedInterfaces();
// ...
IContainer container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// ...
}
Then, in a separate class library I have my static class (again simplified for clarity):
public static class DomainEvents
{
private static IContainer Container { get; set; }
static DomainEvents()
{
//Container = I need get my Autofac container here
}
public static void Register<T>(Action<T> callback) where T : IDomainEvent { /* ... */ }
public static void ClearCallbacks() { /* ... */ }
public static void Raise<T>(T args) where T : IDomainEvent
{
foreach (var handler in Container.Resolve<IEnumerable<IHandle<T>>>())
{
handler.Handle(args);
}
// ...
}
}
Any idea how can I get this?
I need to get or access to my IoC container in a static class.
Any idea how can I get this?
Yes, you don't! Seriously. The pattern with the static DomainEvents class originates from Udi Dahan, but even Udi has admitted that this was a bad design. Static classes that require dependencies of their own are extremely painful to work with. They make the system hard to test and maintain.
Instead, create a IDomainEvents abstraction and inject an implementation of that abstraction into classes that require publishing events. This completely solves the your problem.
You can define your DomainEvents class as follows:
public interface IDomainEvents
{
void Raise<T>(T args) where T : IDomainEvent;
}
// NOTE: DomainEvents depends on Autofac and should therefore be placed INSIDE
// your Composition Root.
private class AutofacDomainEvents : IDomainEvents
{
private readonly IComponentContext context;
public AutofacDomainEvents(IComponentContext context) {
if (context == null) throw new ArgumentNullException("context");
this.context = context;
}
public void Raise<T>(T args) where T : IDomainEvent {
var handlers = this.context.Resolve<IEnumerable<IHandle<T>>>();
foreach (var handler in handlers) {
handler.Handle(args);
}
}
}
And you can register this class as follows:
IContainer container = null;
var builder = new ContainerBuilder();
builder.RegisterType<AutofacDomainEvents>().As<IDomainEvent>()
.InstancePerLifetimeScope();
// Other registrations here
container = builder.Build();
You can create a static method inside your DomainEvents class to inject the container like this:
public static class DomainEvents
{
public static void SetContainer(IContainer container)
{
Container = container;
}
....
}
And then from your ASP.NET application, call this method to inject the container:
DomainEvents.SetContainer(container);
Please note that I am giving you a direct answer to your question. However, here are some issues that I see with this:
Static classes should not be used when the class requires dependencies. In such case, refactor to use a non-static class and use Constructor Injection to inject the dependencies that you need in the class.
Using the container outside of the Composition Root is called Service Location and is considered an anti-pattern.
Class libraries should not use the container or even have a Composition Root. Quoting from the Composition Root article that I referenced:
Only applications should have Composition Roots. Libraries and frameworks shouldn't.

Castle Windsor: How to specify different implementations for different properties of the same type [duplicate]

While registering components in Castle Windsor, how do we bind specific implementation of an interface to a component that has a dependency on that interface. I know in advance which implementation needs to be used by the component.
For example i created a sample console application based on code from several blogs and tutorials.
Following is the code.
public interface IReport
{
void LogReport();
}
public interface ILogger
{
string Log();
}
public class FileLogger : ILogger
{
public string Log()
{
return "Logged data to a file";
}
}
public class DatabaseLogger : ILogger
{
public string Log()
{
return "Logged data to a database";
}
}
public class McAfeeService : IReport
{
private readonly ILogger _logger;
public McAfeeService(ILogger logger)
{
this._logger = logger;
}
public void LogReport()
{
string getLogResult = this._logger.Log();
Console.WriteLine("McAfee Scan has " + getLogResult);
}
}
public class NortonService : IReport
{
private readonly ILogger _logger;
public NortonService(ILogger logger)
{
this._logger = logger;
}
public void LogReport()
{
string getLogResult = this._logger.Log();
Console.WriteLine("Norton Scan has " + getLogResult);
}
}
class Program
{
private static IWindsorContainer container;
static void Main(string[] args)
{
// Register components
container = new WindsorContainer();
container.Register(Component.For<IReport>().ImplementedBy<NortonService>());
container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
IReport service = container.Resolve<IReport>();
service.LogReport();
Console.ReadLine();
}
}
I would like NortonService to always use a Filelogger and McAfeeService to use a Database Logger.
In the above program i am unable to bind NortonService to FileLogger.
How to do it?
The above answers lead me to inline dependencies and the feature service override
Here is the registration code:
container.Register(Component.For<IReport>().ImplementedBy<NortonService>().Named("nortonService"));
container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
container.Register(Component.For<ILogger>().ImplementedBy<DatabaseLogger>());
container.Register(
Component.For<IReport>().ImplementedBy<McAfeeService>().Named("mcafeeService")
.DependsOn(Dependency.OnComponent<ILogger, DatabaseLogger>())
);
IReport mcafeescan = container.Resolve<IReport>("mcafeeService");
mcafeescan.LogReport();
IReport nortonscan = container.Resolve<IReport>("nortonService");
nortonscan.LogReport();
Output:
McAfee Scan has Logged data to a database
Norton Scan has Logged data to a file
I had a problem very like this, two implementation of one interface and two implementation of another interface. I wanted to force usage of particular implementations of those interfaces.
My class structure looked like this -
I looked at the naming convention, but didn't really like it. Instead I used the following -
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()
,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
.DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())
,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
.DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())
,Component.For<MessageOfTheDayController>().LifestyleTransient()
.DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
);
Full info about this approach is here. In the source code provided with that post I show two other ways of achieving the same result.
If you want to do it at runtime, This can be acheived through IHandlerSelector. Write a class that implements IHandlerSelector. It provides a method SelectHandler which will let you define the condition for binding conditionally at runtime. A Handler in this case is a component in Windsor that participates in instance construction. Refer here for more details.
My answer maybe not the best one, you can use naming method to resolve multi implementation:
container.Register(Component.For(typeof(ILogger))
.ImplementedBy(typeof(FileLogger))
.Named("FileLoggerIoC")
.LifestylePerWebRequest() ,
Component.For(typeof(ILogger))
.ImplementedBy(typeof(DatabaseLogger))
.Named("DatabaseLoggerIoC")
.LifestylePerWebRequest());
In your calling functions, you need to resolve it by name :-
var fileLog = container.Resolve("FileLoggerIoC", typeof(ILogger));
var DbLog = container.Resolve("DatabaseLoggerIoC", typeof(ILogger));
Mine method maybe not the best one as people don't like service locator to get the components, you can use this as temporary solution.

Categories

Resources