Something along those lines:
builder.RegisterType<MyType>().As<IType>();
builder.RegisterType<MyType2>().As<IType>();
builder.DeRegisterType<MyType>().As<IType>()
var container = builder.Build();
var types = container.Resolve<IEnumerable<IType>>();
Assert.IsTrue(types.Count == 1);
Assert.IsTrue(types[0].GetType == typeof(MyType2));
Scenario: I go through bunch of assemblies and as I go I register types but I want to
make sure that I have only one implementation of a given type. I need to do this before I create the container. I could track that on my own but it would be nice if Autofac could help me a bit.
This cannot be done directly using the ContainerBuilder, unless you start over with a new one. Mind you, having first built a container you should be able to construct a new container filtering away unwanted types and reusing the registrations from the first container. Like this:
...
var container = builder.Build();
builder = new ContainerBuilder();
var components = container.ComponentRegistry.Registrations
.Where(cr => cr.Activator.LimitType != typeof(LifetimeScope))
.Where(cr => cr.Activator.LimitType != typeof(MyType));
foreach (var c in components)
{
builder.RegisterComponent(c);
}
foreach (var source in container.ComponentRegistry.Sources)
{
cb.RegisterSource(source);
}
container = builder.Build();
This is hardly very elegant but it works. Now, if you could elaborate on why you want to do this, perhaps there is a better way.
Peter L.'s probably got the most straightforward option.
To get around the problem altogether, can you modify the way you're discovering components to filter them in advance of registration? It does seem like there must be an approach that gets around this... It also might be a challenge further down the track to work out which components to keep vs. which to remove.
A more involved approach is to override IEnumerable support to filter out the the things you don't want. I.e. copy and modify this code to create a FilteredCollectionSource that excludes the components you don't want.
var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService);
would become:
var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService)
.Where(reg => /* not a duplicate */);
If you add your FilteredCollectionSource to the builder using RegisterSource() it will should get used instead of the built-in one.
Related
Initially I needed only one queue to be created by the MessageQueueFactory:
container.RegisterSingleton<IMessageQueueFactory>(() => {
var uploadedWaybillsQueuePath = ConfigurationManager
.AppSettings["msmq:UploadedDocumentsQueuePath"];
return new MessageQueueFactory(uploadedWaybillsQueuePath);
});
Now that requirements have changed there's a need to support several queues.
The simplest thing I can do here is to add other paths (stored in app.config) to the factory's constructor and provide methods for each queue:
container.RegisterSingleton<IMessageQueueFactory>(() => {
var uploadedDocsQueuePath = ConfigurationManager
.AppSettings["msmq:UploadedDocumentsQueuePath"];
var requestedDocsQueuePath = ConfigurationManager
.AppSettings["msmq:RequestedDocumentsQueuePath"];
return new MessageQueueFactory(
uploadedWaybillsQueuePath,
requestedDocsQueuePath
);
});
interface IMessageQueueFactory {
MessageQueue CreateUploadedDocsQueue();
MessageQueue CreateRequestedDocsQueue();
}
Is it a poor design? How can it be refactored?
I wouldn't consider this bad design. You need to provide the queue name and having it as an appSetting makes it easier to update them if you need to.
It also feels like the less friction path, which is always good, however I don't quite like it because every time you add a new name you have to change the interface and that's not that nice.
I found this post with some answers that might interest you :
IoC - Multiple implementations support for a single interface
I am trying to create a dependency graph in StructureMap 3 with a chain of decorators:
Each instance has a constructor with multiple arugments, but exactly one argument of an inner IGeocoder, e.g.
public SomeCachingGeocoder(IGeoCoder inner, IFoo somethingElse)
I am hooking them up like this:
For<OviGeoCoder>().Use<OviGeoCoder>();
For<SqlCachingGeocoder>().Use<SqlCachingGeocoder>().Ctor<IGeoCoder>().Is<OviGeoCoder>();
For<RedisCachingGeocoder>().Use<RedisCachingGeocoder>().Ctor<IGeoCoder>().Is<SqlCachingGeocoder>();
For<IGeoCoder>().Use<RedisCachingGeocoder>();
But I get
Bi-directional dependency relationship detected! Check the StructureMap stacktrace below:
1.) Instance of SOAM.Services.IGeoCoder (SOAM.Services.Geocoding.RedisCachingGeocoder)
2.) new RedisCachingGeocoder(Default of IDatabase, Default of IGeoCoder)
3.) SOAM.Services.Geocoding.RedisCachingGeocoder
4.) Instance of SOAM.Services.IGeoCoder (SOAM.Services.Geocoding.RedisCachingGeocoder)
5.) new HomeController(Default of IGeoCoder, Default of IAlertService)
6.) SOAM.Web.Controllers.HomeController
7.) Instance of SOAM.Web.Controllers.HomeController
8.) Container.GetInstance(SOAM.Web.Controllers.HomeController)
Any ideas how to solve this?
DecorateAllWith allows auto-wiring by default and allows stacking decorators in a quite easy way:
For<IGeoCoder>().Use<OviGeoCoder>();
For(typeof(IGeoCoder)).DecorateAllWith(typeof(SqlCachingGeocoder));
For(typeof(IGeoCoder)).DecorateAllWith(typeof(RedisCachingGeocoder));
If for some reason you cannot use DecorateAllWith() then this should work:
var container = new Container(
c =>
{
c.For<IFoo>().Use<Foo>();
c.For<IGeoCoder>().Add<OviGeoCoder>().Named("default");
c.For<IGeoCoder>()
.Add<SqlCachingGeocoder>()
.Ctor<IGeoCoder>()
.Is(ctx => ctx.GetInstance<IGeoCoder>("default"))
.Named("SqlCaching");
c.For<IGeoCoder>()
.Use<RedisCachingGeocoder>()
.Ctor<IGeoCoder>()
.Is(ctx => ctx.GetInstance<IGeoCoder>("SqlCaching"));
});
Wanna find what's the difference when using Use vs Add? Take a look here
I'm using the dictionary adapter as described in this blog post:
http://kozmic.net/2013/11/21/on-strongly-typed-application-settings-with-castle-dictionaryadapter/
for getting app setting dependencies.
I have 2 attributes defined:
AppSettingsFromConfigAttribute - for holding a keyprefix
AppSettingsBehavior : KeyPrefixAttribute, IDictionaryPropertyGetter, IPropertyDescriptorInitializer
which is a carbon copy of the AppSettingsAttribute attribute class in the blog post.
This is the registration:
Configure(component => component.UsingFactoryMethod(
() =>
{
var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));
var prop = new PropertyDescriptor();
prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));
return configFactory.GetAdapter(component.Implementation, new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
})));
So i use my custom attribute to avoid dependencies to Castle.Core throughout my codebase, but try and add the same behavior at runtime through the registration. This is working, the keyprefix part - but not the fetch part. This fails only on first use, not on construction.
If i use the AppSettingsBehavior statically on the interface, it works correctly, fetches and fails on construction. So where am i going wrong in adding behavior to the dictionary adapter?
After a few hours of looking at the source, scratching my head and a coffee. Found a solution :)
Basically in the addbehavior call i get to add dictionary behaviors, while what i need is an interface / property behavior to trigger (pre)fetch. In the source, the guys are checking for attributes on the supplied type all over the place, despite what the method signatures may say - but only taking dictionary initializers from the prop descriptor object, nothing for the interface / properties. Hence, even though the behavior i was adding had the interface behavior - it never got read, only the dictionary behaviors.
So, i use a different call. Instead of calling factory.GetAdapter - i instead get factory.GetAdapterMeta() - which gives me a meta object with a nice Properties getter - which has the collection for the actual interface properties.
So the code becomes:
Configure(component => component.UsingFactoryMethod(
() =>
{
var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));
var prop = new PropertyDescriptor();
prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));
var meta = configFactory.GetAdapterMeta(component.Implementation);
foreach (var entry in meta.Properties)
{
entry.Value.Fetch = true;
}
return meta.CreateInstance(new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
})));
It appears that AutoMapper's methods BeforeMap and AfterMap have a critical bug, which if one is attempting to iterate over a collection of the source object to populate a property of the destination object, those mapping methods execute more than once. See: Extra iterations in a foreach in an AutoMapper map
What I'm trying to do is a bit complicated, so please bear with me.
I have a EF4 many-to-many graph (Games-to-Platforms) I'm trying to build based on incoming form data. In order to build the graph, I take the raw integer ids that come from the form, and then grab the correct Platforms from my repository in order to add them to the Game's collection. You can see my attempt at doing this within BeforeMap in the link I provided above.
The problem is that I'm not sure how to proceed. I need to be able to grab a hold of the destination (Game) object in order to successfully Add the Platforms to the Game. Is something like this possible in ForMember? From what I've read, it doesn't look like a custom resolver would work for me, and I'm not sure how I'd implement a custom type converter given all the moving parts (two entities, repository).
Any ideas or suggestions?
I simply decided to make my own static mapper. Not an ideal, or even great solution, but it works. It can definitely be made more abstract, but I figure it's a band-aid until AutoMapper is fixed. My solution:
public static class GameMapper
{
public static Game Map(IGameRepository repo, AdminGameEditModel formData, Game newGame)
{
newGame.GameID = formData.GameID;
newGame.GameTitle = formData.GameTitle;
newGame.GenreID = formData.GenreID;
newGame.LastModified = DateTime.Now;
newGame.ReviewScore = (short)formData.ReviewScore;
newGame.ReviewText = formData.ReviewText;
newGame.Cons = String.Join("|", formData.Cons);
newGame.Pros = String.Join("|", formData.Pros);
newGame.Slug = formData.Slug;
if (newGame.Platforms != null && newGame.Platforms.Count > 0)
{
var oldPlats = newGame.Platforms.ToArray();
foreach (var oldPlat in oldPlats)
{
newGame.Platforms.Remove(oldPlat);
}
}
foreach (var platId in formData.PlatformIDs)
{
var plat = repo.GetPlatform(platId);
newGame.Platforms.Add(plat);
}
return newGame;
}
}
Unfortunately, I can't make the third parameter an out parameter due to my need to overwrite existing entity data during updating. Again, it's definitely not a pretty, or even good solution, but it does the job. I'm sure the OO gods will smite me at a later date.
I'm trying to find an IOC container that will allow me to have mapping data for a field stored in a database and resolve the interface or object that needs resolved via a string value pulled from the database.
Most of the examples I have seen are using interfaces hard coded in code, I want the interface that needs to be resolved to be dynamic.
This is what I usually see:
var taskController = container.Resolve<ITaskController>();
This is what I would like to see:
var strTaskController = "ITaskController";
var taskController = container.Resolve(strTaskController);
I'm sure I could look through the documentation for all the IOC containers but I am hoping this is an easy question for someone with more IOC experience.
Using Unity you can do what you're looking for. Basically, if you know the full type name, you can do this first:
var type = Type.GetType("Fully.Qualified.Type.Name");
var resolvedInstance = container.Resolve(type);
EDIT: Based on the comment, here's another approach:
string typeName = "MyTypeName";
var type = container.Registrations.FirstOrDefault(r => r.RegisteredType.Name == typeName);
if(type != null)
{
var resolvedInstance = container.Resolve(type.RegisteredType);
}
I think this is the answer I am going with..
Managed Extensibility Framework
http://msdn.microsoft.com/en-us/library/dd460648.aspx
Got to love it when you find a new framework to find the exact solution to your problem.
You can use the IOC container from the Castle project.