Let's assume following basic Project-Setup:
- Core
-- Attributes
--- CustomDisplayNameAttribute : DisplayNameAttribute
- UI
UI represents the MVC Web interface, the core implements all the domain business objects, including self written attributes like CustomDisplayNameAttribute. This attribute contains additional dependencies like a language resolver, which e.g. deals with fallback orders. Hibernate sessions would be another possible dependency.
In earlier projects, these attributes did a global request in order to get the resolver. This is IMO ugly and should be handled differently. Furthermore, Core should stay without HttpContext: since the language-resolver is required per request, it might end up in HttpContext Items Collection.
Now I am quite a beginner with Ninject, and I am not sure if it is the right tool in order to get such dependencies into something like a CustomDisplayNameAttribute?
In words it would be something like this:
If the attribute is created, populate the additional language resolver property with the language resolver from HttpContext Items Collection
If there is no HttpContext (e.g. testing, quartz jobs etc.), get it from somewhere else.
Thx for any inputs
Edit: Sample-Code
namespace Core.Attributes
{
public class CustomDisplayNameAttribute : DisplayNameAttribute
{
private string textCode;
/// <param name="textCode">According to this Text-Code, we will load
/// and resolve the text.</param>
public DeimosDisplayNameAttribute(string textCode)
{
this.textCode = textCode;
}
/// <summary>
/// Load and resolve Text according to Text-Code
/// </summary>
public override string DisplayName
{
get
{
// Load - Ooops: First global access
// --> How can it be injected with IoC?
TextbausteinRepository repo = Root.GetTextBausteinRepository();
var textItem = repo.GetText(textCode);
// Resolve - Ooops: Second global access
// --> How can it be injected with IoC?
TextResolver resolver = Root.GetTextResolver();
return resolver.resolve(textItem);
}
}
}
}
Edit 2: In that context, it seems that there is no way around a global access, like a registry pattern or similar. UI would register the needed data in there, and the attributes would access it from there. We started to think about storing it in ThreadLocal<T>, but this seems not really save due to the fact that there is a possibility of thread-swapping during the life-cycle. So there seems no way around storing HttpContext in the registry layer. For more info about this subject, see [Cup(Of T)][1].
I don't think this is possible, because data attributes are not run-time dispatched like filters are. As such, there's no place to intercept the creation and inject what you're looking for.
Related
So I have a need for injecting a number of different services into an authorization attribute I'm using. For simplicity I will leave this to show the configuration manager.
public class FeatureAuthorizeAttribute : AuthorizeAttribute
{
public IConfigurationManager ConfigurationManager;
private readonly string _feature;
public FeatureAuthorizeAttribute(string feature)
{
_feature = feature;
var test = ConfigurationManager.GetCdnPath();
}
}
Which would be used as follows
[FeatureAuthorize("Admin")]
I have tried to use constructor injection
public FeatureAuthorizeAttribute(string feature, IConfigurationManager configurationManager)
{
ConfigurationManager = configurationManager;
_feature = feature
}
However this just causes an error when I attempt
[FeatureAuthorize("Admin", IConfigurationManager)]
Which seems like the wrong way to go about it in the first place. I'm assuming that I need to register my custom authorization attribute with the container to get it to start picking up
Instead of trying to use Dependency Injection with attributes (which you can't do in any sane, useful way), create Passive Attributes.
Specifically, in this case, assuming that this is an ASP.NET MVC scenario, you can't derive from AuthorizeAttribute. Instead, you should make your Authorization service look for your custom attribute, and implement IAuthorizationFilter. Then add the filter to your application's configuration.
More details can be found in this answer: https://stackoverflow.com/a/7194467/126014.
I am developing an MVC app to serve multiple domains - each is a branch of a larger company.
A LocalBranch class stores details such as phone, address, email, location coordinates etc.
I want to create a single instance of this class per http request and have it available throughout the application - from within controllers, views, some helper classes and other code.
Is there a recommended way of doing this?
Right now I have it as a property on a BaseController and use ViewBagto pass it to views. But I would prefer it strongly typed in Views if possible.
I don't want to put it in an application variable, because we need to serve different values to different domains.
I would rather avoid a session variable if possible because we might scale up to use multiple servers in the future, and I've heard this doesn't play well with sessions.
Please feel free to update tags / title if you think there is a clearer way of expressing what I'm after. Thank you.
The best way to maintain your state in a web application per request is simply use the HttpContext class.
You need to store your state(LocalBranch) as an Item in the HttpContext:
HttpContext.Current.Items.Add("LocalBranch", GetLocalBranch());
You can fetch the Item all across your application like this:
LocalBranch branch = HttpContext.Current.Items["LocalBranch"] as LocalBranch;
The Items property is simply a key value Dictionary. The value is an object. You will have to check for nulls and this is really similar to the Session object you know. The main difference is the scope. The HttpContext is a dot net object that has a lifetime of an http request.
Now using the HttpContext the way I've shown you is the simplest way to do it.
You can go two steps forward and use a framework called Unity and add a lifetime to your objects.
Unity does much more and the lifetime management is just one gem.
You can create a custom HttpContext lifetime that generates objects per request. Something like this.
And them all you need to do is:
1.Register you LocalBranch class with the HttpContext lifetime.
2.Add a static Current property which will use the Unity container and resolve the correct instance of LocalBranch.
3.Use it something like this: LocalBranch.Current
BTW, you can use Unity's dependency injection for injecting objects into controllers and other modules. That's a better practice then just using the static Current property.
You kind of have two questions here. The first is "How do I create a single instance of this class per HttpRequest?" The second is "How do I make this available to strongly typed views?"
The first has pretty much been answered by #amir-popovich to use dependency injection. However, FWIW I would probably use Ninject instead of Unity (just preference, really) and I would probably implement it differently. I would not use HttpContext, and simply build a service (which is instanciated using Ninject's OnePerHttpRequest Module, passing the domain as an argument to get the proper values).
Then, in order to add these LocalBranch values to your strongly typed View Model, you can first create a base view model which holds this type:
public class BaseViewModel
{
public LocalBranch Branch {get;set;}
}
Then, make all of your current view models inherit this base type
public MyViewModel : BaseViewModel
{
public string SomeValue {get;set;}
}
Then in your controller, it is easy enough to add these values from the service you created from the first step
public ActionResult SomeAction()
{
var vm = new MyViewModel();
vm.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject
//do other stuff
return View(vm);
}
However, that gets pretty tedious to add that to each controller action, so you can instead create a Result Filter to add it for you:
public class LocalBranchResultFilter : FilterAttribute, IResultFilter
{
public void OnResultExecuting(ResultExecutingContext filterContext)
{
//This method gets invoked before the ActionResult is executed.
filterContext.Controller.ViewData.Model.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject
}
}
Now, you can just decorate your Controller and/or Actions with the filter (you could even set it in the Global Filters if you want).
You can embed the child actions into your layout or a view. You can even cache its output so you don't keep re-querying the database.
controller
[ChildActionOnly]
[OutputCache(Duration=500, VaryByParam="*")]
public ActionResult Info()
{
var localBranch = db.GetLocalBranch();
return PartialView("_Info", localBranch);
}
_Info view
This bit will get inserted into your other views
#model LocalBranch
<span>#Model.address</span>
<span>#Model.phone</span>
Use in _Layout or other view
<p>lorem ipsum...</p>
#Html.Action("Info")
I'm trying to use NHibernate for a new app with a legacy database. It's going pretty well but I'm stuck and can't find a good solution for a problem.
Let's say I have this model :
a Service table (Id, ServiceName..)
a Movie table (Id, Title, ...)
a Contents table which associates a service and a movie (IdContent, Name, IdMovie, IdService)
So I mapped this and it all went good. Now I can retrieve a movie, get all the contents associated, ...
My app is a movies shop "generator". Each "service" is in fact a different shop, when a user enter my website, he's redirected to one of the shops and obviously, I must show him only movies available for his shop. The idea is : user comes, his service is recognized, I present him movies which have contents linked to his service. I need to be able to retrieve all contents for a movie for the backoffice too.
I'm trying to find the most transparent way to accomplish this with NHibernate. I can't really make changes to the db model.
I thought about a few solutions :
Add the service condition into all my queries. Would work but it's a bit cumbersome. The model is very complex and has tons of tables/queries..
Use nhibernate filter. Seemed ideal and worked pretty good, I added the filter on serviceid in all my mappings and did the EnableFilter as soon as my user's service was recognized but.. nhibernate filtered collections don't work with 2nd lvl cache (redis in my case) and 2nd lvl cache usage is mandatory.
Add computed properties to my object like Movie.PublishedContents(Int32 serviceId). Probably would work but requires to write a lot of code and "pollutes" my domain.
Add new entities inheriting from my nhibernate entity like a PublishedMovie : Movie wich only presents the contextual data
None of these really satisfies me. Is there a good way to do this ?
Thanks !
You're asking about multi-tenancy with all the tenants in the same database. I've handled that scenario effectively using Ninject dependency injection. In my application the tenant is called "manual" and I'll use that in the sample code.
The route needs to contain the tenant e.g.
{manual}/{controller}/{action}/{id}
A constraint can be set on the tenant to limit the allowed tenants.
I use Ninject to configure and supply the ISessionFactory as a singleton and ISession in session-per-request strategy. This is encapsulated using Ninject Provider classes.
I do the filtering using lightweight repository classes, e.g.
public class ManualRepository
{
private readonly int _manualId;
private readonly ISession _session;
public ManualRepository(int manualId, ISession session)
{
_manualId = manualId;
_session = session;
}
public IQueryable<Manual> GetManual()
{
return _session.Query<Manual>().Where(m => m.ManualId == _manualId);
}
}
If you want pretty urls you'll need to translate the tenant route parameter into its corresponding database value. I have these set up in web.config and I load them into a dictionary at startup. An IRouteConstraint implementation reads the "manual" route value, looks it up, and sets the "manualId" route value.
Ninject can handle injecting the ISession into the repository and the repository into the controller. Any queries in the controller actions must be based on the repository method so that the filter is applied. The trick is injecting the manualId from the routing value. In NinjectWebCommon I have two methods to accomplish this:
private static int GetManualIdForRequest()
{
var httpContext = HttpContext.Current;
var routeValues = httpContext.Request.RequestContext.RouteData.Values;
if (routeValues.ContainsKey("manualId"))
{
return int.Parse(routeValues["manualId"].ToString());
}
const string msg = "Route does not contain 'manualId' required to construct object.";
throw new HttpException((int)HttpStatusCode.BadRequest, msg);
}
/// <summary>
/// Binding extension that injects the manualId from route data values to the ctor.
/// </summary>
private static void WithManualIdConstructor<T>(this IBindingWithSyntax<T> binding)
{
binding.WithConstructorArgument("manualId", context => GetManualIdForRequest());
}
And the repository bindings are declared to inject the manualId. There may be a better way to accomplish this through conventions.
kernel.Bind<ManualRepository>().ToSelf().WithManualIdConstructor();
The end result is that queries follow the pattern
var manual = _manualRepository
.GetManual()
.Where(m => m.EffectiveDate <= DateTime.Today)
.Select(m => new ManualView
{
ManualId = m.ManualId,
ManualName = m.Name
}).List();
and I don't need to worry about filtering per tenant in my queries.
As for the 2nd level cache, I don't use it in this app but my understanding is that you can set the cache region to segregate tenants. This should get you started: http://ayende.com/blog/1708/nhibernate-caching-the-secong-level-cache-space-is-shared
Right now I'm having an issue with a Singleton that I just wrote for use in ASP.NET MVC -- My Singleton looks like this:
public sealed class RequestGenerator : IRequestGenerator
{
// Singleton pattern
private RequestGenerator()
{
requestList = new Stack<Request>();
appSettings = new WebAppSettings();
}
private static volatile RequestGenerator instance = new RequestGenerator();
private static Stack<Request> requestList = new Stack<Request>();
// abstraction layer for accessing web.config
private static IAppSettings appSettings = new WebAppSettings();
// used for "lock"-ing to prevent race conditions
private static object syncRoot = new object();
// public accessor for singleton
public static IRequestGenerator Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new RequestGenerator();
}
}
}
return instance;
}
}
private const string REQUESTID = "RequestID";
// Find functions
private Request FindRequest(string component, string requestId)
private List<Request> FindAllRequests(string component, string requestId)
#region Public Methods required by Interface
// Gets and increments last Request ID from Web.Config, creates new Request, and returns RequestID
public string GetID(string component, string userId)
// Changes state of Request to "submitted"
public void SetID(string component, string requestId)
// Changes state of Request to "success" or "failure" and records result for later output
public void CloseID(string component, string requestId, bool success, string result)
// Verifies that Component has generated a Request of this ID
public bool VerifyID(string component, string requestId)
// Verifies that Component has generated a Request of this ID and is owned by specified UserId
public bool VerifyID(string component, string userId, string requestId)
// Returns State of Request ID (Open, Submitted, etc.)
public Status GetState(string component, string requestId)
// Returns Result String of Success or Failure.
public string GetResult(string component, string requestId)
#endregion
}
And my controller code looks like this:
public ViewResult SomeAction()
{
private IRequestGenerator reqGen = RequestGenerator.Instance;
string requestId = reqGen.GetID(someComponentName, someUserId);
return View(requestId);
}
Everything works okay the first time I hit the controller. "reqGen" is assigned the instance of the Singleton. A new instance of Request is added to the internal list of the Singleton. And then we return a View(). The next time I hit this controller's SomeAction(), I'm expecting the Singleton to contain the List with the instance of SomeClass that I had just added, but instead the List is empty.
What's happened? Has Garbage Collection gobbled up my object? Is there something special I need to consider when implementing the Singleton pattern in ASP.NET MVC?
Thanks!
EDIT: Ahh, the lightbulb just went on. So each new page request takes place in a completely new process! Got it. (my background is in desktop application development, so this is a different paradigm for me...)
EDIT2: Sure, here's some more clarification. My application needed a request number system where something being requested needed a unique ID, but I had no DB available. But it had to be available to every user to log the state of each request. I also realized that it could double as a way to regulate the session, say, if a use double-clicked the request button. A singleton seemed like the way to go, but realizing that each request is in its own process basically eliminates the singleton. And I guess that also eliminates the static class, right?
EDIT3: ok, I've added the actual code that I'm working with (minus the implementation of each Method, for simplicity sake...) I hope this is clearer.
EDIT4: I'm awarding the green check mark to Chris as I'm beginning to realize that an application-level singleton is just like having a Global (and global's are evil, right?) -- All kidding aside, the best option really is to have a DB and SQLite seems like the best fit for now, although I can definitely see myself moving to an Oracle instance in the future. Unfortunately, the best option then would be to use an ORM, but that's another learning curve to climb. bugger.
EDIT5: Last edit, I swear. :-)
So I tried using HttpRuntime.Cache, but was surprised to find that my cache was getting flushed/invalidated constantly and couldn't figure out what was going on. Well, I was getting tripped up by a side-effect of something else I was doing: Writing to "Web.config"
The Answer --> Unbeknownst to me, when "web.config" is altered in anyway, the application is RESTARTED! Yup, everything gets thrown away. My singleton, my cache, everything. Gah. No wonder nothing was working right. Looks like writing back to web.config is generally bad practice which I shall now eschew.
Thanks again to everyone who helped me out with this quandary.
The singleton is specific to the processing instance. A new instance is being generated for each page request. Page requests are generally considered stateless so data from one doesn't just stick around for another.
In order to get this to work at the application level, the instance variable will have to be declared there. See this question for a hint on how to create an application level variable. Note that this would make it available across all requests.. which isn't always what you want.
Of course, if you are trying to implement some type of session state then you might just use session or use some type of caching procedure.
UPDATE
Based on your edits: A static class should not maintain data. It's purpose is to simply group some common methods together, but it shouldn't store data between method calls. A singleton is an altogether different thing in that it is a class that you only want one object to be created for the request.
Neither of those seem to be what you want.
Now, having an application level singleton would be available to the entire application, but that crosses requests and would have to be coded accordingly.
It almost sounds like you are trying to build an in memory data store. You could go down the path of utilizing one of the various caching mechanisms like .NET Page.Cache, MemCache, or Enterprise Library's Caching Application Block.
However, all of those have the problem of getting cleared in the event the worker process hosting the application gets recycled.. Which can happen at the worst times.. And will happen based on random things like memory usage, some timer expired, a certain number of page recompiles, etc.
Instead, I'd highly recommend using some type of persisted storage. Whether that be just xml files that you read/write from or embedding something like SQL Lite into the application. SQL Lite is a very lightweight database that doesn't require installation on the server; you just need the assemblies.
You can use Dependency Injection to control the life of the class. Here's the line you could add in your web.config if you were using Castle Windsor.
<component id="MySingleton" service="IMySingleton, MyInterfaceAssembly"
type="MySingleton, MyImplementationAssembly" lifestyle="Singleton" />
Of course, the topic of wiring up your application to use DI is beyond my answer, but either you're using it and this answer helps you or you can take a peak at the concept and fall in love with it. :)
I have been looking at various dependency injection frameworks for .NET as I feel the project I am working on would greatly benefit from it. While I think I have a good grasp of the capabilities of these frameworks, I am still a little unclear on how best to introduce them into a large system. Most demos (understandably) tend to be of quite simple classes that have one or two dependencies.
I have three questions...
First, how do you deal with those common but uninteresting dependencies, e.g. ILog, IApplicationSettings, IPermissions, IAudit. It seems overkill for every class to have these as parameters in their constructor. Would it be better to use a static instance of the DI container to get these when they are needed?
MyClass(ILog log, IAudit audit, IPermissions permissions, IApplicationSettings settings)
// ... versus ...
ILog log = DIContainer.Get<ILog>();
Second, how do you approach dependencies that might be used, but may be expensive to create. Example - a class might have a dependency on an ICDBurner interface but not want the concrete implementation to be created unless the CD Burning feature was actually used. Do you pass in interfaces to factories (e.g. ICDBurnerFactory) in the constructor, or do you again go with some static way of getting directly to the DI Container and ask for it at the point it is needed?
Third, suppose you have a large Windows Forms application, in which the top level GUI component (e.g. MainForm) is the parent of potentially hundreds of sub-panels or modal forms, each of which may have several dependencies. Does this mean that MainForm should be set up to have as dependencies the superset of all the dependencies of its children? And if you did so, wouldn't this end up creating a huge self-inflating monster that constructs every single class it could ever need the moment you create MainForm, wasting time and memory in the process?
Well, while you can do this as described in other answers I believe there is more important thing to be answered regarding your example and that is that you are probably violating SRP principle with class having many dependencies.
What I would consider in your example is breaking up the class in couple of more coherent classes with focused concerns and thus the number of their dependencies would fall down.
Nikola's law of SRP and DI
"Any class having more than 3
dependencies should be questioned for
SRP violation"
(To avoid lengthy answer, I posted in detail my answers on IoC and SRP blog post)
First: Add the simple dependencies to your constructor as needed. There is no need to add every type to every constructor, just add the ones you need. Need another one, just expand the constructor. Performance should not be a big thing as most of these types are likely to be singletons so already created after the first call. Do not use a static DI Container to create other objects. Instead add the DI Container to itself so it can resolve itself as a dependency. So something like this (assuming Unity for the moment)
IUnityContainer container = new UnityContainer();
container.RegisterInstance<IUnityContainer>(container);
This way you can just add a dependency on IUnityContainer and use that to create expensive or seldom needed objects. The main advantage is that it is much easier when unit testing as there are no static dependencies.
Second: No need to pass in a factory class. Using the technique above you can use the DI container itself to create expensive objects when needed.
Three: Add the DI container and the light singleton dependencies to the main form and create the rest through the DI container as needed. Takes a little more code but as you said the startup cost and memory consumption of the mainform would go through the roof if you create everything at startup time.
First:
You could inject these objects, when needed, as members instead of in the constructor. That way you don't have to make changes to the constructor as your usage changes, and you also don't need to use a static.
Second:
Pass in some sort of builder or factory.
Third:
Any class should only have those dependencies that it itself requires. Subclasses should be injected with their own specific dependencies.
I have a similar case related to the "expensive to create and might be used", where in my own IoC implementation, I'm adding automagic support for factory services.
Basically, instead of this:
public SomeService(ICDBurner burner)
{
}
you would do this:
public SomeService(IServiceFactory<ICDBurner> burnerFactory)
{
}
ICDBurner burner = burnerFactory.Create();
This has two advantages:
Behind the scenes, the service container that resolved your service is also used to resolve the burner, if and when it is requested
This alleviates the concerns I've seen before in this kind of case where the typical way would be to inject the service container itself as a parameter to your service, basically saying "This service requires other services, but I'm not going to easily tell you which ones"
The factory object is rather easy to make, and solves a lot of problems.
Here's my factory class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LVK.IoC.Interfaces;
using System.Diagnostics;
namespace LVK.IoC
{
/// <summary>
/// This class is used to implement <see cref="IServiceFactory{T}"/> for all
/// services automatically.
/// </summary>
[DebuggerDisplay("AutoServiceFactory (Type={typeof(T)}, Policy={Policy})")]
internal class AutoServiceFactory<T> : ServiceBase, IServiceFactory<T>
{
#region Private Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly String _Policy;
#endregion
#region Construction & Destruction
/// <summary>
/// Initializes a new instance of the <see cref="AutoServiceFactory<T>"/> class.
/// </summary>
/// <param name="serviceContainer">The service container involved.</param>
/// <param name="policy">The policy to use when resolving the service.</param>
/// <exception cref="ArgumentNullException"><paramref name="serviceContainer"/> is <c>null</c>.</exception>
public AutoServiceFactory(IServiceContainer serviceContainer, String policy)
: base(serviceContainer)
{
_Policy = policy;
}
/// <summary>
/// Initializes a new instance of the <see cref="AutoServiceFactory<T>"/> class.
/// </summary>
/// <param name="serviceContainer">The service container involved.</param>
/// <exception cref="ArgumentNullException"><paramref name="serviceContainer"/> is <c>null</c>.</exception>
public AutoServiceFactory(IServiceContainer serviceContainer)
: this(serviceContainer, null)
{
// Do nothing here
}
#endregion
#region Public Properties
/// <summary>
/// Gets the policy that will be used when the service is resolved.
/// </summary>
public String Policy
{
get
{
return _Policy;
}
}
#endregion
#region IServiceFactory<T> Members
/// <summary>
/// Constructs a new service of the correct type and returns it.
/// </summary>
/// <returns>The created service.</returns>
public IService<T> Create()
{
return MyServiceContainer.Resolve<T>(_Policy);
}
#endregion
}
}
Basically, when I build the service container from my service container builder class, all service registrations are automatically given another co-service, implementing IServiceFactory for that service, unless the programmer has explicitly registered on him/her-self for that service. The above service is then used, with one parameter specifying the policy (which can be null if policies aren't used).
This allows me to do this:
var builder = new ServiceContainerBuilder();
builder.Register<ISomeService>()
.From.ConcreteType<SomeService>();
using (var container = builder.Build())
{
using (var factory = container.Resolve<IServiceFactory<ISomeService>>())
{
using (var service = factory.Instance.Create())
{
service.Instance.DoSomethingAwesomeHere();
}
}
}
Of course, a more typical use would be with your CD Burner object. In the above code I would resolve the service instead of course, but it's an illustration of what happens.
So with your cd burner service instead:
var builder = new ServiceContainerBuilder();
builder.Register<ICDBurner>()
.From.ConcreteType<CDBurner>();
builder.Register<ISomeService>()
.From.ConcreteType<SomeService>(); // constructor used in the top of answer
using (var container = builder.Build())
{
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingHere();
}
}
inside the service, you could now have a service, a factory service, which knows how to resolve your cd burner service upon request. This is useful for the following reasons:
You might want to resolve more than one service at the same time (burn two discs simultaneously?)
You might not need it, and it could be costly to create, so you only resolve it if needed
You might need to resolve, dispose, resolve, dispose, multiple times, instead of hoping/trying to clean up an existing service instance
You're also flagging in your constructor which services you need and which ones you might need
Here's two at the same time:
using (var service1 = container.Resolve<ISomeService>())
using (var service2 = container.Resolve<ISomeService>())
{
service1.Instance.DoSomethingHere();
service2.Instance.DoSomethingHere();
}
Here's two after each other, not reusing the same service:
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingHere();
}
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingElseHere();
}
First:
You might approach it by creating a container to hold your "uninteresting" dependencies (ILog, ICache, IApplicationSettings, etc), and use constructor injection to inject that, then internal to the constructor, hydrate the fields of the service from container.Resolve() ? I'm not sure I'd like that, but, well, it's a possibility.
Alternatively, you might like to use the new IServiceLocator common interface (http://blogs.msdn.com/gblock/archive/2008/10/02/iservicelocator-a-step-toward-ioc-container-service-locator-detente.aspx) instead of injecting the dependencies?
Second:
You could use setter injection for the optional/on-demand dependencies? I think I would go for injecting factories and new up from there on-demand.
To partially answer my first question, I've just found a blog post by Jeremy Miller, showing how Structure Map and setter injection can be used to auto-populate public properties of your objects. He uses ILogger as an example:
var container = new Container(r =>
{
r.FillAllPropertiesOfType<ILogger>().TheDefault.Is
.ConstructedBy(context => new Logger(context.ParentType));
});
This means that any classes with an ILogger property, e.g.:
public class ClassWithLogger
{
public ILogger Logger { get; set; }
}
public class ClassWithLogger2
{
public ILogger Logger { get; set; }
}
will have their Logger property automatically set up when constructed:
container.GetInstance<ClassWithLogger>();