Structuremap - Override registration - c#

Is it possible to register an interface in a registry, then "re-register" it to override the first registration?
I.E.:
For<ISomeInterface>().Use<SomeClass>();
For<ISomeInterface>().Use<SomeClassExtension>();
What I want here on runtime is that my object factory returns SomeClassExtension when I ask for ISomeInterface.
Thanks in advance!

Good news, I found out that yes. It all depends on the order that the registry rules are added to the object factory container. So if you are using multiple registry classes as I was doing, you need to find a way to give a priority to add them to the container.
In other words, instead of using the .LookForRegistries() which gets all the Registry classes in the wrong order, try to find all the Registry files, set them in the order you want and add them manually to the object factory container:
ObjectFactory.Container.Configure(x => x.AddRegistry(registry));
That way, you have full control on what rules you want.
Hope it helps :)

I just wanted to add my solution to the problem when I needed to override some parts of a registry in my SpecFlow test.
I did find this thread pretty early in my search, but it didnĀ“t really help me find the solution, so I hope it will help you.
My problem was that the "DataContext" in "StoreRegistry" (used by the application) use the "HybridHttpOrThreadLocalScoped" and I needed it to be "Transient" in my tests.
The code looked like this:
[Binding]
public class MySpecFlowContext
{
...
[BeforeFeature]
private static void InitializeObjectFactories()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<StoreRegistry>();
x.AddRegistry<CommonRegistry>();
});
}
}
To override the scope setting you will need to explicitly set it in the registration.
And the override needs to be below what is overridden
The working code looks like this:
[Binding]
public class MySpecFlowContext
{
...
[BeforeFeature]
private static void InitializeObjectFactories()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<StoreRegistry>();
x.AddRegistry<CommonRegistry>();
x.AddRegistry<RegistryOverrideForTest>();
});
}
class RegistryOverrideForTest : Registry
{
public RegistryOverrideForTest()
{
//NOTE: type of scope is needed when overriding the registered classes/interfaces, when leaving it empty the scope will be what was registered originally, f ex "HybridHttpOrThreadLocalScoped" in my case.
For<DataContext>()
.Transient()
.Use<DataContext>()
.Ctor<string>("connection").Is(ConnectionBuilder.GetConnectionString());
}
}
}

Related

Best practice for application-wide initialization shared by several Autofac components? (Aspose license in this case.)

We're using Autofac and some of our components use Aspose libraries, which require a license. The license is loaded like this:
public class MyAutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// [Register stuff]
LoadAsposeLicense();
}
private void LoadAsposeLicense()
{
// Load the Aspose license.
string licenseFile = Path.Combine(Assembly.GetExecutingAssembly().Location, "..", "Aspose.Total.lic");
Aspose.Slides.License license = new Aspose.Slides.License();
license.SetLicense(licenseFile);
}
}
I thought that was a good idea until I wanted to reuse the DLL from some code that doesn't need the Aspose functionality. We have a license for all Aspose products, but right now, we only use the PowerPoint stuff. However, in the future that may change and we may have other components that will need the Word functionality. The license would be the same, but I guess it would have to be initialized separately.
I am wondering whether it could make sense to introduce a simple license component like this, which would be registered as a singleton (or I could be even lazier and put the code into a static constructor):
class AsposeSlidesLicense
{
public AsposeSlidesLicense()
{
string licenseFile = Path.Combine(Assembly.GetExecutingAssembly().Location, "..", "Aspose.Total.lic");
Aspose.Slides.License license = new Aspose.Slides.License();
license.SetLicense(licenseFile);
}
}
I could then use it like this:
class MyComponentThatUsesAspose : ISlidesCreatorService
{
public MyComponentThatUsesAspose(AsposeSlidesLicense license)
{
// Dummy constructor to make sure the license is loaded
}
public void CreateSlide()
{
// Use Aspose library
}
}
But since the license dependency (parameter) has no other function than to trigger the license loading, I'm a bit worried, it may be optimized away either by the compiler, Resharper or another developer.
So my question is:
What's the best place to put initialization code like this, that may be required by several components to have run once?
And only when those services are needed (components are instantiated)?
To run code when a component is requested you can use the OnActivating autofac lifetime event
You can listen to such event at registration and each time a component is requested, this event will be fired.
builder.RegisterType<LicenseVerifier>()
.As<ILicenseVerifier>()
.SingleInstance()
builder.RegisterType<YourComponent>()
.OnActivating(e => e.Context.Resolve<ILicenseVerifier>().EnsureLicense())
in your EnsureLicense you can do whatever you want to ensure the license is applied.
If you have lots of component it may be a good idea to wrap the OnActivating call to a custom method extension and write something like :
builder.RegisterType<YourComponent>()
.WithLicense()
another option would be to add an attribute to YourComponent
[RequireLicense]
public class YourComponent {}
and create an autofac Module that will add the OnActivating part to all components having the attribute.
If you want to run code when the application starts Autofac has 2 mechanisms.
You can implements IStartable it's an Autofac interface that run when the container is built.
public class StartupMessageWriter : IStartable
{
public void Start()
{
Console.WriteLine("App is starting up!");
}
}
and register it like this :
builder
.RegisterType<StartupMessageWriter>()
.As<IStartable>()
.SingleInstance();
You can register a component with AutoActivate. In such case the component will be build when the container is built
builder
.RegisterType<TypeRequiringWarmStart>()
.AsSelf()
.AutoActivate();
you can also create your own interface and resolve these after container initialization.
you can find more information about autofac in the running code at container build documentation.

Nancy create singleton with constructor parameters

I'm using Nancy with TinyIoC to solve the dependencies.
One dependency in particular needs to be application-lifecycle singleton.
If I do it with a default constructor it works:
container.Register<IFoo, Foo>().AsSingleton(); // WORKS
but if i try this with some arguments on the contructor it does not:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>())).AsSingleton();
// FAILS with error "Cannot convert current registration of Nancy.TinyIoc.TinyIoCContainer+DelegateFactory to singleton"
Whithout .AsSingleton(), it works again, but I don't get a singleton:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>()));
// Works, but Foo is not singleton
Any Ideas? I think the mistake should be obvious but I can't find it.
I've used up all my google-foo.
EDIT
The code runs here:
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
// here
}
}
What you're doing there is telling TinyIOC "every time you want one of these, call my delegate", so if you want to use that method you have to handle the singleton aspect yourself.
Unless you particularly need the deferred creation it's easier to do:
container.Register<IFoo>(new Foo("value", c.Resolve<ILogger>()));
That will then always use that instance whenever you want an IFoo.

Achieving DI without 3rd party framework

I am writing a plugin as part of a plugin architecture. The way plugins are created is via reflection and CreateInstance. Therefore the default constructor is called. This code I cannot touch and I am trying to find a sensible way to use DI without the ability to use a framework.
I believe I have 3 options:
i) Poor Man's DI (PMDI)
ii) Factory Pattern
iii) TinyIOC or similar (one cs file that handles DI)
I started looking at PMDI but then a dependency needed another dependency so I ended up with something similar to this which is ugly and could get worse:
public MyMainPluginClass() : this(new Repo(new Logger()))
{
}
public MyMainPluginClass(IRepo repo)
{
}
I then moved onto the idea of a Factory Pattern but could not find any decent demo code. I assume I would have something like this:
public static FactoryUtility
{
public static IRepo GetRepo()
{
return new Repo(GetLogger());
}
public static ILogger GetLogger()
{
return new Logger();
}
}
public MyMainPluginClass() : this(FactoryUtility.GetRepo())
{
}
public MyMainPluginClass(IRepo repo)
{
}
Is that how it would look?
I then came across TinyIOC which is one class that does all the dependency registering but I believe it requires to be setup in a Program.cs which I don't have in a class library. If someone has any experience using this could it be used like so:
public MyMainPluginClass()
{
var container = TinyIoCContainer.Current;
container.AutoRegister();
var implementation = container.Resolve<IRepo>();
MyMainPluginClass(implementation);
}
public MyMainPluginClass(IRepo repo)
{
}
Are there any alternative approaches to achieve DI without using a 3rd party library and if not which approach would choose from above?
NOTE: The code above has not been compiled and is just an idea of what I think would work. Please post corrections if they are valid approaches.
Since you're using .NET 4, you might want to consider using MEF, as it's built into the framework itself. This looks like fairly straightforward DI, which MEF handles well, as it's intended mainly for extensibility.
For details, see the Learn More page on the MEF CodePlex site.
I went with TinyIOC in the end. Unfortunately the plugin's constructor gets called several times before its actually up and running. I simply set a boolean to prevent registration being called several times and therefore it allows me to simply auto-register dependencies and off we go.
public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{
}
public MyMainPluginClass(IRepo repo)
{
}
public static class FactoryUtility
{
private static bool Initialized = false;
public static IRepo SetupIOC()
{
var container = TinyIoCContainer.Current;
if (!Initialized)
{
container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });
Initialized = true;
}
var result = container.Resolve<IRepo>();
return result;
}
}
If I absolutely don't want to add a dependency to a DI container, I like to use my own TinyIOC (sorry about the name, didn't know it was taken), which for small projects gives me the same semantics as using a container, but clocks in at below 200 LOC.
If you are interested, here is the code: https://gist.github.com/ad7608e2ae10b0f04229

Unity - resolving without resolve()

I would like to just markup a property with an attribute [DoInjection] and have unity do the injection. I don't want to have to use prop = Unity.Resolve(type). Thats a pain and messy. Does unity provide attributes to do this or do I have to build my own?
Edit: register in App.Main
ISessionFactory sf = new SessionFactory();
container.RegisterType<IRepository, CustomerRepository>(new InjectionConstructor(sf.CurrentUoW));
container.RegisterInstance<IUnitOfWork>(sf.CurrentUoW);
Using [Dependancy] on IUnitOfWork propery in ClassX other class but it's always null. Do I need to build ClassX instance using Unity to get this to work? It looks like I do have to. I don't like that.
Unity has a DependencyAttribute you can use for this:
public class MyObject
{
private SomeOtherObject _dependentObject;
[Dependency]
public SomeOtherObject DependentObject
{
get { return _dependentObject; }
set { _dependentObject = value; }
}
}
http://msdn.microsoft.com/en-us/library/ff650198.aspx
Based on your question, it sounds like you might be trying to use Unity in the wrong spot and your design sense was telling you it didn't feel right. You should only see Unity where you bootstrap your application. That's your Main method in a console app or Global.asax in a web or wcf app. The idea is to keep relying on dependencies all the way up the chain until you get to where you bootstrap and resolve just that one top level object using your IoC container. In a console app, I do this:
class Program
{
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container
.AddExtension(new ConfigureForConsole(args))
.Resolve<MyApplication>()
.Execute();
}
}
}
http://www.agileatwork.com/console-application-with-ioc/
In this case, MyApplication is my top level object (it doesn't need to be an interface here). The ConfigureForConsole is just a one-off custom container extension that has all the RegisterType lines in there. Alternatively you could initialize the container from App.Config here. The idea though is that your Main method has almost nothing in it. Another benefit of this approach is that it makes your code more portable. I find that console apps usually turn into windows services and keeping things clean here makes that transition pretty painless.

what is the replacement for Application_Start in MVCTurbine?

Apparently, this method no longer gets called... In there we have code for configuring AutoMapper, and for setting model binders.
I know there is a "new" way to do model binders, but... shouldn't I still be able to do it "the old way" until I get that implemented?
Specifically, I have two lines left from my old Application_Start() method that I have been unable to get working:
AutoMapperConfiguration.Configure();
ModelBinders.Binders[typeof (ModuleEditModel)] = new DerivedModelBinder();
I've tried simply popping those into the constructor, right after the call to: ServiceLocatorManager.SetLocatorProvider(() => new StructureMapServiceLocator());
And that runs, but.. it seems somehow not to take effect. In running the application it is clear that AutoMapper isn't happy, doesn't have the mappings it is supposed to have, etc.
I answered this question out on the Turbine Discussion board on CodePlex. Here's the source for making the changes you ask for:
public class MvcApplication : TurbineApplication {
static MvcApplication() {
// Register the IoC that you want Mvc Turbine to use!
// Everything else is wired automatically
// For now, let's use the Unity IoC
ServiceLocatorManager.SetLocatorProvider(() => new UnityServiceLocator());
}
public override void Startup(){
// Gets called when the application starts up
// and before all the stuff that Turbine wires up
}
public override void Shutdown() {
// Gets called when the application shuts down
// and before any cleanup is done by Turbine
}
}
Hope this helps!

Categories

Resources