Say I have a singleton-ish, factory-ish, reflection-ish class that receives some input, and spits back a new instance of a concrete implementation of some interface. What kind of design is this? Is there a better way to do what I want?
Here's some code to illustrate the point:
using System;
using System.Collections.Generic;
// static factory class
public static class ArticleFactory
{
// given an SKU, store the Type object for an IArticle object
private static Dictionary<string, Type> articleRegistry = new Dictionary<string, Type>();
// allow public registration of SKU-to-Type object relationships
public static bool Register(string sku, Type typeInfo)
{
if(!articleRegistry.ContainsKey(sku))
{
articleRegistry.Add(sku, typeInfo);
return true;
}
return false;
}
// given a SKU, give me an instance of the related IArticle object
public static IArticle NewArticle(string sku)
{
if(articleRegistry.ContainsKey(sku))
{
// use reflection to invoke the default constructor
return articleRegistry[sku].GetConstructor(Types.EmptyTypes).Invoke(null) as IArticle;
}
return null;
}
}
// example concrete-implementation of an IArticle
public class Jeans : IArticle
{
public decimal GetPrice() { return SomeDecimal(); }
}
// WHERE DO I CALL THIS LINE?
ArticleFactory.Register("0929-291", typeof(Jeans));
// Later on, if another group needs to write the class for Snowboards,
// how can they self-register their class, without changing any "Main()"
// or "Page_Init()" function?
Looks like you've already identified the pattern. It's the Factory Method Pattern. Or rather, a somewhat half-baked implementation of one. A slightly better approach would be to first make it an interface:
public interface IArticleFactory
{
IArticle CreateArticle(string sku);
}
Then implement the factory without any Reflection at all:
public class MyArticleFactory
{
private Dictionary<string, Func<IArticle>> instantiators =
new Dictionary<string, Func<Iarticle>>();
public MyArticleFactory()
{
Register("Jeans", () => new Jeans());
Register("Shirt", () => new Shirt());
// etc.
}
public IArticle CreateArticle(string sku)
{
Func<IArticle> instantiator;
if (creators.TryGetValue(sku, out instantiator))
return instantiator();
throw new UnknownSkuException(sku);
}
protected void Register(string sku, Func<IArticle> instantiator)
{
creators.Add(sku, instantiator);
}
}
A few important differences:
Registration isn't public, nor should it be. Registration usually either resides in a configuration file somewhere or is private.
Does not require the IArticle concrete types to have a default parameterless constructor. This can easily register articles with parameterized constructors (as long as it knows what parameters to use).
Throws an exception on duplicate registrations. I don't like the idea of simply returning false; if you try to register the same factory method twice, that ought to be considered a bug.
It's not static. You can replace this factory with a different factory. You can unit-test it.
Of course, an even better approach would just be to use any of the myriad of existing .NET Dependency Injection/Inversion of Control Frameworks, such as Ninject or AutoFac.
I don't know if it has a "name" as such, but it looks like some kind of manual service resolver. The problem I can see (from experience, sadly) is that it is inflexible in real terms, in that:
the registration only has a single configuration
it is hard to unit test
Personally I'd look at an IoC container if I was doing this in a new system; the IoC can handle this relationship, and provide a lot more capabilities for free (lifetimes, enrichment, extra setup, etc), and solve many associated problems.
BTW, it may be easier to:
return Activator.CreateInstance(articleRegistry[sku]);
I think what you're doing here is basically Dependency Injection (or Inversion of Control is what the cool kids call it). Have a look at these links:
Explanation from Wikipedia: http://en.wikipedia.org/wiki/Dependency_Injection
Two DI .Net frameworks:
StructureMap: http://structuremap.sourceforge.net/QuickStart.htm
Castle Windsor: http://www.castleproject.org/container/index.html
It's just a factory pattern that happens to use reflection in its implementation. Rather than using reflection, though, it would probably be more efficient to simply put instances of factory classes directly in the dictionary, though this might require some boilerplate code.
Related
What is a good (object oriented) way of setting a property of a class which implements an interface, when that property doesn't always exist in all classes that implement that same interface?
e.g.
Let's say I have an interface
public interface IDataRepository {
public DataStructure GetData(); // DataStructure is an arbitrary class, doesn't matter for this example
}
Now I also have two classes that inherit from this
public class DatabaseRepository : IDataRepository {
public DataStructure GetData()
{
// get data from database
}
}
and
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; }
public DataStructure GetData() {
// get data from files
}
}
Now my client method doesn't necessarily know what the repository is but here's what I want to do...
private DataStructure ReadData(IDataRepository repository)
{
repository.WorkingFolder = #"C:\Data"; // What is the best way of doing this?
return repository.GetData();
}
obviously the above code won't work and I could do...
if (repository is FileRepository) {
((FileRepository)repository).WorkingFolder = #"C:\Data";
}
or add WorkingFolder as a property of the interface (and therefore all the classes that implement it) even though in most cases it's irrelevant.
but both of these (esp. the first one) seem very inelegant and not very object oriented. What is the oop way of doing this kind of thing?
Edit
The obvious question is if the method doesn't know what repository is, how can it know the correct value for WorkingFolder... But the above is an over-simplification of what I'm trying to do, so let's just say it can find out...
Apparently your ReadData method can't actually accept any type of repository. It is only able to handle a FileRepository. That's what it expects, and that's what it needs to do its job. Given that, that's what it should actually accept as its parameter, rather than an interface that doesn't actually provide a contract that is sufficient for it to do its job.
The entire point of having an interface is so that anyone using that interface can use it without caring what the implementation is. So if you do want to use the interface you need to include enough information in the interface's definition such that it provides every operation that anyone using the interface needs, otherwise you're better off just not using it at all (at least for that specific operation).
As for the specific example given, you should probably just be providing an already configured repository, that has whatever values it needs in order to allow this method to do its work, as a parameter. It doesn't make sense for a method that's reading a value from an arbitrary repository to be configuring that repository at all. That is, if it really is reading something from an arbitrary repository.
As others have said in the comments, you should initialise these properties in the constructor. This is where you know what type you're creating, so you also know what arguments its constructor requires / can set those there.
Once you've initialised the object, you can just pass it around / have anything using that class operate against its interface.
Example:
public void Main(string[] args)
{
var myRepo = new FileRepository(args[0]); //Here's where we set the working directory
var myThing = new Thing();
var data = myThing.ReadData(myRepo);// of course, the current implementation means you could just call `myRepo.GetData()` directly, since ReadData just passes out the same response; but presumably that method adds some additional value..
Console.WriteLine(data.ToString());
}
Supporting Code
public class DatabaseRepository : IDataRepository {
DbConnection connection; //you may want a connection string or something else; going with this type just to illustrate that this constructor uses a different type to the FileRepo's
public DatabaseRepository(DbConnection connection)
{
this.connection = connection;
}
public DataStructure GetData()
{
// get data from database
}
}
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; } //Do you need set? Generally best to keep it constant after initialisation unless there's good reason to change it
public FileRepository (string workingFolder)
{
this.WorkingFolder = workingFolder;
}
public DataStructure GetData() {
// get data from files
}
}
How do I call the code that creates the class
i.e. maybe you've implemented a really basic factory pattern like so, and want to know how to provide arguments:
public class DataRepositoryFactory
{
Type baseType = typeof(IDataRepository);
IDictionary<string, Type> typeMap = new Dictionary<string, Type>() {
{"File", typeof(FileRepository) }
,{"Db", typeof(DatabaseRepository) }
}
public void RegisterType(string typeName, Type type)
{
if (!baseType.IsAssignableFrom(type)) throw new ArgumentException(nameof(type));
typeMap.Add(typeName, type);
}
public IDataRepository GetDataRepository(string typeName)
{
return (IDataRepository)Activator.CreateInstance(typeMap[typeName]);
}
}
(For a more complex example of a factory, see https://web.archive.org/web/20140414013728/http://tranxcoder.wordpress.com/2008/07/11/a-generic-factory-in-c).
I.e. in this scenario, when you call the factory you know what type you want, but you're only giving it a string to name/identify that class. You could add a params object[] args to your GetDataRepository method, allowing you to call it like so:
var myRepo = myDataRepositoryFactory.GetDataRepository("File", "c:\somewhere\something.dat");
That's a good approach / is actually what's used on the linked example above. However, it means that your call to this code differs for different types; since if we use variables instead of hardcoded values as in the above example we can't simply do the below, since myRepoType could be set to "Db", whilst "myFilePath" would be a string:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myFilePath);
That's fixable by calling:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myArgs);
i.e. where myArgs is an object[], giving all of the values required in the desired order to initialise the type. The piece to populate object[] with the required values could then take place at the same point at which you decided you wanted the type to be a file repo vs database repo. However, this approach isn't that clean / casting to and from objects stops you from getting help from the compiler.
So how do I improve things?
There are a few options. One is to replace the need to use object[] by instead creating a type to hold your arguments. e.g.
public interface IDataRepositoryConfiguration
{
//nothing required; this is just so we've got a common base class
}
public class FileRepositoryConfiguration: IDataRepositoryConfiguration
{
public string WorkingFolder {get;set;}
}
public class FileRepository : IDataRepository {
public FileRepository (IDataRepositoryConfiguration configuration)
{
var config = configuration as FileRepositoryConfiguration;
if (config == null) throw new ArgumentException(nameof(configuration)); //improve by having different errors for null config vs config of unsupported type
this.WorkingFolder = config.WorkingFolder;
}
//...
}
This still has some issues; i.e. we may pass a DatabaseRepositoryConfiguration as our IRepositoryConfiguration when creating a FileRepository, in which case we'd get the AgumentNullException at runtime; but this does avoid issues should parameters change order, and makes it less of a headache to code / debug.
Could it be further improved?
Dependency Injection offers one solution. This could be used along the lines of the code below (i.e. you create instances of each of your classes, providing the required arguments, and give each instance a name, so that you can later fetch that instantiation. Exactly what that code looks like would depend on the dependency injection library you used:
//setting up your repositories
var container = new Container();
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.For<IDataRepository>().Add(new FileRepository("\\server\share\customers")).Named("customers");
config.For<IDataRepository>().Add(new FileRepository("\\server\share\invoices")).Named("invoices");
config.For<IDataRepository>().Add(new DatabaseRepository(new DbConnection(configurationString))).Named("persist");
config.For<IDataRepository>().Use("persist"); // Optionally set a default
config.Populate(services);
});
//then later when you need to use it...
public DataStructure ImportCustomers(IContainer container)
{
var customerRepo = container.GetInstance<IDataRepository>("customers");
return customerRepo.GetData();
}
I'm sure there are many other approaches, and exactly what approach to use depends on how your program will operate. Hopefully the above is enough to get you past your current problem; but if you find you're still struggling please post a new question with more detail / saying where you're still having issues having considered these points.
If possible, I'd just put the value for that property in the constructor or create a subinterface, like others suggested.
If it's not possible, C# 7.X (don't remember the exact minor version) has a nice code structure for conditional casting:
IDataRepository repo = new FileRepository();
if (repo is FileRepository fileRepo)
{
fileRepo.WorkingFolder = "some dir";
}
However in your case, you should probably rethink your architecture and always pass (or even better always create) a repository object which is ready to be used.
a) Put it into the Inferface definitions. Deal with any "NotImplemented" Exceptions. You always have to expect those with Interfaces anyway.
For example, IEnumerable has a Reset() function. But in most cases it is not implemented. It is not even supposed to be implemented in most cases. Afaik it is only there for Backwards Compatabilty with some old COM stuff.
b) make a sub-interface just for the property
c) Verify the Interface is properly implemented via is checks (throw exceptions thows if nessesary, like Array.Sort will throw a InvalidOperation one), generic constraints, proper argument types and the like.
I have read a lot about this topic, but couldn't grasp it all the way.
I am trying to use the Ninject.Extensions.Factory instead of my factory to create new objects depending on user input. I want to fully use the Ninject functionality and the IoC concept.
Now the code looks like this:
interface IFeatureFactory
{
IFeature createFeature(int input);
}
and:
class BasicFeatureFactory : IFeatureFactory
{
public IFeature createFeature(int input)
{
switch (input)
{
case 1:
return new FirstFeature();
case 2:
return new SecondFeature();
default:
return null;
}
}
}
In the future, the IFeature will have dependencies so I want to do it the IoC way.
EDIT:
consumer class - the IFeatureFactory and IUILayer are injected into the FeatureService constructor and resolved using Ninject.
private IFeatureFactory featureFactory;
private IUILayer uiHandler;
public FeatureService(IFeatureFactory featureFactory, IUILayer uiHandler)
{
this.featureFactory = featureFactory;
this.uiHandler = uiHandler;
}
public void startService()
{
int userSelection = 0;
uiHandler.displayMenu();
userSelection = uiHandler.getSelection();
while (userSelection != 5)
{
IFeature feature = featureFactory.createFeature(userSelection);
if (feature != null)
{
IResult result = feature.execFeature();
uiHandler.displayResult(result);
}
else
{
uiHandler.displayErrorMessage();
}
uiHandler.displayMenu();
userSelection = uiHandler.getSelection();
}
}
and IFeature class:
public interface IFeature
{
IResult execFeature();
}
Bindings:
public override void Load()
{
Bind<IFeatureFactory>().To<BasicFeatureFactory>();
Bind<IUILayer>().To<ConsoleUILayer>();
}
How can I convert this Factory Pattern to IoC with the Ninject.Extensions.Factory? keep in mind the creation of the IFeature is dependent on the user input.
To me it is look like you have 2 options to refactor your code to get the full benefits of ninject.
The way you're working now is no different than pure di (which there is nothing wrong about it and it is better it some cases) but as you said you want to fully use ninject functionality.
Option one
Instead of injecting IFeatureFactory into FeatureService inject the interface IFeatureProvider which will look like this:
public interface IFeatureProvider
{
IFeature GetFeature(int featureType);
}
Now your FeatureService will get the requested features from this provider instead of the factory.
You will need to implement IFeatureProvider and for that you will need 2 more interfaces IFirstFeatureFactory and ISecondFeatureFactory:
public interface IFirstFeatureFactory
{
IFeature CreateFirstFeature();
}
public interface ISecondFeatureFactory
{
IFeature CreateSecondFeature();
}
And now IFeatureProvider impelementaion:
public class FeatureProvider: IFeatureProvider
{
private readonly IFirstFeatureFactory _firstFeatureFactory;
private readonly ISecondFeatureFactory _secondFeatureFactory;
public FeatureProvider(IFirstFeatureFactory firstFeatureFactory, ISecondFeatureFactory secondFeatureFactory)
{
_firstFeatureFactory=firstFeatureFactory;
_secondFeatureFactory=secondFeatureFactory;
}
public IFeautre GetFeature(int featureType)
{
switch(featureType)
{
case 1:
return _firstFeatureFactory.CreateFirstFeature();
case 2:
return _secondFeatureFactory.CreateSecondFeature();
default:
return null;
}
}
}
the thing you should notice that i just extract the object who is responsible for the 'new' into another interface.
We will not implement the two factory interfaces as ninject will do it for us if we will bind it properly.
The binding:
Bind<IFeature>().ToFeature<FirstFeature>().NamedLikeFactoryMethod((IFirstFeatureFactory o) => o.CreateFirstFeature());
Bind<IFeature>().ToFeature<SecondFeature>().NamedLikeFactoryMethod((ISecondFeatureFactory o) => o.CreateSecondFeature());
Bind<IFirstFeatureFactory>().ToFactory();
Bind<ISecondFeatureFactory>().ToFactory();
Bind<IFeatureProvider>().To<FeatureProivder>();
This 'NameLikeFactoryMethod' binding is equivalent the using of named binding as i did here and it is now the recommended way by ninject for factories.
The importent thing to notice here you do not implement IFirstFeatureFactory and ISecondFeatureFactory by yourself and you're using ninject functionallity for that.
The major disadvantage of this option is when we need to add more features we will need to create except for the feature itself another FeatureFactory and also change the FeatureProvider to handle it as well.
If the features are not changed very often this option can be good and simple but if they do it can become maintenance nightmare and that is why i suggest option 2.
Option two
In this option we will not create any provider class at all and will put all the creation logic inside the factory.
IFeatureFactory interface will look pretty similar to the one you have now, but instead of using an int as parameter we will use a string (is will suit better with the named binding as we will see soon).
public interface IFeatureFactory
{
IFeature CreateFeature(string featureName);
}
We will not implement this interfaces by ourselves and let ninject do it for us, however we will need to tell ninject to use the first parameter of CearteFeature to detect which implementation to instantiate(FirstFeatue or SecondFeature).
For that we will need custom instance provider with this behavior as the StandardInstanceProvider using other convention to choose which implementation to instantiate(the default convention in this article).
Fortunately ninject show as exactly how we can implement it very quickly by UseFirstArgumentAsNameInstanceProvider.
Now the binding:
Bind<IFeature>().To<FirstFeature>().Named("FirstFeature");
Bind<IFeature>().To<FirstFeature>().Named("SecondFeature");
Bind<IFeatureFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());
The things to notice here:
We will not implement the factory interface by ourselves.
We are using named binding for each implementation and we will get the implementation from the factory according to the featureName we will pass to the factory method (this is why i prefer the parameter to be string).
Notice that if you pass feature name that is not "FirstFeature" or "SecondFeature" exception will be thrown.
We are using UseFirstArgumentAsNameInstanceProvider as our instance provider for our factory as mentioned before.
This has solved the problem in the first option as if we want to add new feature we well just need to create it and bind it to his interface with his name.
Now the client of the factory can ask from the factory feature with this new name without the need of changes in other classes.
Conslucsion
By choosing one of this options above over pure di we will get the benefits of letting ninject kernel create our object in the factories instead of doing all the 'new' on our own.
Although there is nothing wrong about not using IoC container this can really helps us in cases there is a big dependencies graph inside IFeature implementations as ninject will inject them for us.
By doing one of this options we are fully using ninject functionality without using a 'Service locator' which is considered as an anti pattern.
You can inject the features into the BasicFeatureFactory's constructor.
class BasicFeatureFactory : IFeatureFactory
{
FirstFeature feature1;
SecondFeature feature2;
public BasicFeatureFactory(FirstFeature feature1, SecondFeature feature2) {
this.feature1 = feature1;
this.feature2 = feature2;
}
public IFeature createFeature(int input) {
switch (input) {
case 1: return this.feature1;
case 2: return this.feature2;
default: return null;
}
}
}
I am currently stuck at trying to write a factory class that doesn't rely on service location.
The only other alternative I can think of is to use constructor injection to inject all possible instances, but that may lead to surprises as classes are passed via reference.
It is also possibly going to be costly and messy once the number of possible providers grow.
The providers themselves are full complex classes that have their own dependencies so manual construction is out of the picture.
Updated service location example:
public class ProviderFactory : IProviderFactory
{
private readonly IProviderConfigurationService _providerConfigurationService;
public enum SearchType
{
Foo,
Bar
}
public ProviderFactory(IProviderConfigurationService providerConfigurationService)
{
_providerConfigurationService = providerConfigurationService;
}
public Collection<IProvider> GetProviderInstances(SearchType searchType)
{
// Provider configuration service will read a XML/DB store to retrieve list of search providers applicable for a search type
var providerList = _providerConfigurationService.GetProviderList(searchType);
return new Collection<IProvider>(providerList.ForEach(x=> ServiceLocator.GetInstance(typeof(x))).ToList()) ;
}
}
What are my other options? I am currently using Unity for DI.
An alternative is to pass a Func<Type, object> to the constructor and to implement the function through your container:
unity.RegisterInstance<Func<Type, object>>(t => unity.Resolve(t))
Then in your class:
public ProviderFactory(Func<Type, object> createFunc, IProviderConfigurationService pcs)
{
_createFunc = createFunc;
}
public Collection<IProvider> GetProviderInstances(SearchType searchType)
{
var providerList = _providerConfigurationService.GetProviderList(searchType);
return new Collection<IProvider>(providerList.Select(_createFunc).ToList());
}
You are missing an abstraction.
Your ProviderFactory should implement an IProviderFactory abstraction. This way you can place that interface in a base library of your application and you can place the ProviderFactory implementation inside your Composition Root. For code that lives inside your composition root, it is okay to reference the DI library, and in that case you're not using service location.
I have recently solved a very similar issue in my own code by using a DI framework. To satisfy Dependency Inversion, the factory constructor should accept an interface (as the other answers have said), but to get the framework to inject the right type is tricky without having a massive list of arguments detailing each possible concretion.
SimpleInjector allows you to register all concretions of a given abstraction with:
Container.RegisterCollection(typeof(IProvider), new [] {typeof(TKnown).Assembly,...});
Your XML could list the (possibly external) assemblies where the concretions are defined and you could build the assembly array from there. Then your factory just needs to accept them all and pick one, perhaps based on the searchType you mentioned.
public class ProviderFactory
{
private List<IProvider> providers;
public ProviderFactory(IEnumerable<IProvider> providers)
{
this.providers = providers.ToList();
}
public IProvider GetProvider(string searchType)
{
// using a switch here would open the factory to modification
// which would break OCP
var provider = providers.SingleOrDefault(concretion => concretion.GetType().Name == searchType);
if (provider == null) throw new Exception("No provider found of that type. Are you missing an assembly in the RegisterCollection for IProvider?");
return provider;
}
I know I'm way late to the party on this but assuming other folks don't see this approach as problematic, it might be useful.
So we have ran into what seems like a very common issue with StructureMap and IoC containers in general I assume. Bidirectiona/Circuar dependencies.
Given the following code, it is currently causing a circular dependency since we have it 'autowiring' properties.
public class ServiceA:IServiceA
{
public IServiceB ServiceBDependency {get;set;}
}
public class ServiceB:IServiceB
{
public IServiceA ServiceADependency {get;set;}
}
I see the 'dependency' of each of these on eachother, however, I feel that as a property, they are not true dependencies which is what separates them from using constructor injection.
It seems that there should be a way for these services to be resolved...and then have the properties injected after the objects have been created?
I know of various ways to get around this, including the true clean way of rearchitecting my services, but i am curious as to what options I have with instantiation and service registration with StructureMap. It seems like a fairly common issue that would need a solution.
I'd like to show you my approach. I am using only the setter injection. And we often have many objcets referencing each other, in our web app. E.g. IUserFacade requires IUserState on user creation while IUserState requires IUserFacade on userState deletion (to check for constraint).
e.g.:
public interface IUserFacade
{
... // User facade Add, Update, Delete
IUserStateFacade { set; }
}
public interface IUserStateFacade
{
...
IUserFacade { set; }
}
In reality, we have many objects with cross references, and even more complicated. And it would really be very costy, if all the referenced objects should be created each time, even if not used during the request. We need the "lazy", the proxy objects to be placed in the setters.
The way how to do it, is a mix of the: 1) StructureMap (IoC top) and 2) Castle (proxying top) libraries. Below I will show some snippets of objects needed for this solution. More could be found inside open source project Catharsis
Wrapper. This object would be injected into each Property by SM (StructureMap) instead of real implementor. It is the sleeping implementation. It is waiting for a first call. If it will never happen (IUserFacade is deleting user, no need to access referenced IUserStateFacade during such request) this wrapper will sleep for ever (request). Once touched, SM will create the real object and Wrapper will pass all calls to that.
The Castle interceptor:
public class Wrapper : IInterceptor
{
object _lazy;
protected readonly Type Type;
public Wrapper(Type type)
{
Type = type;
}
public void Intercept(IInvocation invocation)
{
if (_lazy.IsNull()) // lazily instantiate the instance
{
_lazy = ObjectFactory.GetInstance(Type);
}
try
{
var method = invocation.Method;
if (method.ContainsGenericParameters)
{
method = method.MakeGenericMethod(invocation.GenericArguments);
}
invocation.ReturnValue = method.Invoke(_lazy, invocation.Arguments);
}
catch (TargetInvocationException ex)
{
// PublishingManager.Publish(.... // publish exception
throw;
}
}
}
ProxyInstance. Now, we need an object, clear and understandable to SM. That object will be mapped to all interfaces (IUserFacade...) Instead of returning implementation of the UserFacade.
We can also use our custom AOP filters here.
This ProxyInstance will be provided with the real implementor type, and building up the Wrapper.
The StructureMap Instance:
public class ProxyInstance : Instance
{
protected readonly ProxyGenerator Factory = new ProxyGenerator();
protected readonly Type ConcreteType;
public ProxyInstance(Type type)
{
ConcreteType = type; // the type for our Wrapper, the real implementation
}
protected override object build(Type pluginType, BuildSession session)
{
var aopFilters =
// my custom way how to inject more AOP filters
AopFilterManager.GetFilters()
// the core for us, one of the interceptors is our Wrapper
.Union(new[] { new Wrapper(ConcreteType) })
.ToArray();
// Castle will emit a proxy for us, but the Wrapper will do the job
var proxy = Factory
.CreateClassProxy(ConcreteType, AopFilterManager.AopOptions, aopFilters);
return proxy;
}
And now just use some standard way how to map it in the SM (I am using custom ProxyConvention but it is out of the scope here). Let's use simplified explicit mapping:
registry
.For<IUserFacade>()
.HybridHttpOrThreadLocalScoped()
.Use(new ProxyInstance(typeof(UserFacade)));
...
Also, each of our objects created via SM, implements IService. So, the default setter injection could be set like this:
registry.SetAllProperties
(
set => set.TypeMatches
(
type => type
.GetInterfaces()
.Any(i => i.IsEquivalentTo(typeof(IService)))
)
);
From that moment, when we need to work with a IUserFacade (the direct ObjectFactory call, or accessed via Wrapper), we recieve the real implementor. All its properties (setter injection) will be pre-populated with our ProxyInstance / Wrapper.
If any of these properties is accessed, e.g. IUserStateFacade the same (discribed above for IUserFacade) will happen again.
Because the Lifecycle is Thread or Request based, we have only one implementor in runtime/web request
Because we do inject the Wrappers while using setter injection, no issues with circular infinite loops. Only the first level is injected each time
All of our reports are created from object graphs that are translated from our domain objects. To enable this, we have a Translator class for each report, and have been using Dependency Injection for passing in dependencies.
This worked great, and would yield nice classes structured like this:
public class CheckTranslator : ICheckTranslator
{
public CheckTranslator (IEmployeeService empSvc
, IPaycheckService paySvc)
{
_empSvc = empSvc;
_paySvc = paySvc;
}
public Check CreateCheck()
{
//do the translation...
}
}
However, in some cases the mapping has many different grouping options. As a result, the c-tor would turn into a mix of class dependencies and parameters.
public class CheckTranslator : ICheckTranslator
{
public CheckTranslator (IEmployeeService empSvc
, IPaycheckService paySvc
, bool doTranslateStubData
, bool doAttachLogo)
{
_empSvc = empSvc;
_paySvc = paySvc;
_doTranslateStubData = doTranslateStubData;
_doAttachLogo = doAttachLogo;
}
public Check CreateCheck()
{
//do the translation...
}
}
Now, we can still test it, but it no longer really works with an IoC container, at least in a clean fashion. Plus, we can no longer call the CreateCheck twice if the settings are different for each check.
While I recognize it's a problem, I don't necessarily see the right solution. It seems kind of strange to create a Factory for each class ... or is this the best way?
Shot in the dark here, but could you move those parameters to the method instead?
In other words:
public Check CreateCheck(bool doTranslateStubData, bool doAttachLogo)
{
//do the translation...
}
Do those parameters have to be passed in via the constructor?
(Note - if your response to this is "there are too many methods for that to be practical", then part of the problem may be that the abstraction is too coarse).
Another option (it's really hard to say without understanding the domain model and injection patterns) would be to introduce a parameter object that is itself managed by the injector:
public interface ICheckConfiguration
{
bool AttachLogo { get; }
bool TranslateStubData { get; }
}
Then inject this with the constructor:
public CheckTranslator (IEmployeeService empSvc, IPaycheckService paySvc,
ICheckConfiguration config)
{
// etc.
}
This should be enough. You can then create a concrete CheckConfiguration class that takes those two bool properties in its constructor, and configure your container to create different instances of the parameter object (interface) based on a higher-level DI parameter.
The last thing I think I should mention is that just because you're using DI doesn't mean that everything has to be managed by the container. It's not such a bad thing to create CheckTranslator objects in an ad-hoc fashion if there's only one kind of "translator". As long as the translator still depends on abstractions, which it does here, then maybe you shouldn't be injecting it at all, just let higher-level DI-enabled classes create them ad-hoc.