Given a DbContext that implements 2 interfaces like so:
public interface IQueryEntities
{
IQueryable<User> Users { get; }
IQueryable<Computer> Computers { get; }
// other IQueryable<T> get properties
}
public interface IUnitOfWork
{
int SaveChanges();
}
public class MyContext : DbContext, IQueryEntities, IUnitOfWork
{
// implement interfaces using EF
}
First question, is it a bad idea to separate out the query aspects of DbContext (IDbSets) from the command aspects (SaveChanges)? I am exploring a refactor to the above because there are a lot of cases where we just need to query data, without saving anything.
The problem I'm running into involves unity DI, which currently injects MyDbContext using a singleton-per-http-context lifetime for the IUnitOfWork interface. I'm not sure how to go about setting up injection for the IQueryEntities interface so that it will reuse an existing DbContext instance that may have already been injected against the IUnitOfWork interface. Or vice versa. Is this even possible?
Here is the current lifetime manager that reuses previously-injected instances of IUnitOfWork in the same http context:
public class UnityHttpContextLifetimeManager : LifetimeManager
{
private const string KeyFormat = "SingletonPerCallContext_{0}";
private readonly string _key;
public UnityHttpContextLifetimeManager()
{
_key = string.Format(KeyFormat, Guid.NewGuid());
}
public override object GetValue()
{
return HttpContext.Current.Items[_key];
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[_key] = newValue;
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(_key);
}
}
By the way if there is a way to do this, I would prefer to do it in unity web.config section rather than compiled c# bootstrapper.
Update
With help from onof I was able to get this working, however my config looks different from what he suggested. Am I doing something wrong? When I don't give each interface the lifetime manager, one HttpContext ends up with multiple instances of the DbContext. Only when I give all 3 the lifetime manager does it reuse the same DbContext instance across a single request for both interfaces. Is something wrong with this config?
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="MyApp.MyNameSpace" />
<assembly name="MyApp" />
<alias alias="singleton-per-http-context"
type="MyApp.MyNameSpace.UnityHttpContextLifetimeManager, MyApp" />
<container>
<register type="MyContext">
<lifetime type="singleton-per-http-context" />
</register>
<register type="IUnitOfWork" mapTo="MyContext">
<lifetime type="singleton-per-http-context" />
</register>
<register type="IQueryEntities" mapTo="MyContext">
<lifetime type="singleton-per-http-context" />
</register>
...
</container>
is it a bad idea to separate out the query aspects of DbContext
(IDbSets) from the command aspects (SaveChanges)?
I think it's a good idea, because of Interface Segregation Principle, which states that each client should see only the interface it needs to do its work.
To register, i would do:
container.RegisterType<MyContext>(new UnityHttpContextLifetimeManager());
container.RegisterType<IQueryEntities, MyContext>();
container.RegisterType<IUnitOfWork, MyContext>();
AFAIK it's the only way to share the same instance, once the object created.
To do it at design-time (in web.config), it's straightforward:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="MyApp.MyNameSpace" />
<assembly name="MyApp" />
<container>
<register type="MyContext" >
<lifetime type="UnityHttpContextLifetimeManager" />
</register>
<register type="IQueryEntities" mapTo="MyContext" />
<register type="IUnitOfWork" mapTo="MyContext" />
</container>
You need to register one interface as singleton and the other will automatically follow.
container.RegisterType<IQueryEntities, MyContext>(new UnityHttpContextLifetimeManager());
container.RegisterType<IUnitOfWork, MyContext>();
Assuming that your LifetimeManager works correctly this would scope the lifetime of a instance of MyContext to the HttpContext and the mapping from IUnitOfWork would reuse the same instance as the target of the mapping is the same.
Related
I use Simple injector but somehow i get error as stated in subject. I tried many things before i decided to post this question for instance this is not working for me. I get the following exception when I call Validate:
Validation error message:
The configuration is invalid. The following diagnostic warnings were reported:
-[Disposable Transient Component] AlbumsController is registered as transient, but implements IDisposable.
-[Disposable Transient Component] ArtistsController is registered as transient, but implements IDisposable.
-[Disposable Transient Component] HomeController is registered as transient, but implements IDisposable.
See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.
Application_Start
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IRepository<Artist>, ArtistRepository>(Lifestyle.Scoped);
container.Register<IRepository<Album>, AlbumRepository>(Lifestyle.Scoped);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
I tried to add Lifestyle.Scoped to my registrations as follows:
container.Register<IRepository<Artist>, ArtistRepository>(Lifestyle.Scoped);
container.Register<IRepository<Album>, AlbumRepository>(Lifestyle.Scoped);
Controllers:
Note: Repositories implement IDisposable.
public class HomeController : Controller
{
...
}
public class AlbumsController : Controller
{
readonly IRepository<Album> _repository;
public AlbumsController(IRepository<Album> repository)
{
_repository = repository;
}
...
}
Other details:
My controllers do not override the protected virtual void Dispose(bool) method.
I'm using Simple Injector v4.4.0
I'm using the web integration packages v3.2.7
Based on the supplied demo project I was indeed able to reproduce the issue.
The problem is in the referenced packages:
<package id="SimpleInjector" version="4.4.0" targetFramework="net46" />
<package id="SimpleInjector.Integration.Web" version="3.2.7" targetFramework="net46" />
<package id="SimpleInjector.Integration.Web.Mvc" version="3.2.7" targetFramework="net46" />
As you can see the packages for MVC are from another major branch.
If you update everything to 4.4.0 your problem goes away.
Apart from this, the error message is not telling you to implement IDisposable in your repositories. SimpleInjector, and any other tool for that matter, is not able to decide this for you.
You should decide for yourself if you need that. If you would also inject the DbContext, which is best practice anyway, there is no need to implement IDisposable at all in your repository assuming the current implementations won't change much.
I have a solution with several class library projects and a WCF web service project already in it. The dependency Injection is handled in Unity 2.1 where in web config file of the WCF project I have registered my new class library project as below.
<container name="unityDI">
<register type="INewProcess" mapTo="NewProcess"/>
<register type="ISomeService" mapTo="SomeService">
<constructor>
<param name="newProcess" type="INewProcess" />
<param name="Service1" type="IService1" />
<param name="repository1" type="IRepository1" />
</constructor>
</register>
In the class library project I added to this solution NewProcess class is where the client will consume the library.
That is the class where I do initiate the dependency handling process to handle the dependencies within the class library. this library implements the strategy pattern for handling validations based on different workflows and few other helper classes which used implement different utilities for this validation.
Below is the code I have in NewProcess class
public class NewProcess : INewProcess
{
private readonly IKernel _kernel = new StandardKernel(new NewProcessValidationsLibraryNinjectModule());
/// <inheritdoc />
public Tuple<string, IDictionary<string, string>> DetermineCandidate(string val1, string val2, string val3)
{
var newValidationObjectFactory = _kernel.Get<INewValidationObjectFactory>();
return newValidationObjectFactory.DetermineValidationStrategy(val1, val2, val3);
}
/// <inheritdoc />
public NewStatusObject GetSomeReceivedStatus(NewStatusObject newStatusObject)
{
var statusReceiveStatusChecker = _kernel.Get<IStatusReceiveStatusChecker>();
return statusReceiveStatusChecker.GetNewReceiveStatus(newStatusObject);
}
}
And in the NewProcessValidationsLibraryNinjectModule i have the below code
public class NewProcessValidationsLibraryNinjectModule : NinjectModule
{
public override void Load()
{
Kernel.Bind(x => x.FromThisAssembly().SelectAllClasses().BindAllInterfaces());
}
}
Can someone please let me know will there be any memory leak related issues while using both Unity and Ninject at the same time as above? Or is this the correct way of using both Unity and Ninject within the same solution? Will the new up of StandardKernel end up in memory issues?
I had a lengthy look at the comments I received and did some testing at run time and found that the way I have implemented the DI in my library it was loading and unloading the Ninject Kernel on request basis which is not the way you want your DI container to work.
It should load all the dependencies when you load it first time.
To resolve this issue I opt to use Unity across my solution. Apparently this move made the library calls faster and I do not have to worry about using 2 different DI containers in the same solution and complexities it can bring to your solution.
We are seeing unexpected behavior from Unity when registering the same concrete class to different unnamed instances. In this scenario, the registrations appear to interfere with each other in unexpected ways.
We provide a framework to other applications where we want to inject
different interfaces (i.e. different views on a common concept) with
potentially the same class that may be initialized in different ways,
either with different injected parameters and/or different values.
When the framework uses the class via one interface it can expect
potentially different behavior than when it uses the class via a
different interface.We therefore register two interfaces with the
same mapTo class with different initializations (and potentially
lifetimes).It is logical to expect that when we register type by
different interfaces in Unity that they do not interfere with each
other. This is true for named instances, but not for unnamed
instances.
There are three logical outcomes of attempting to
register different interfaces mapped to the same class:
Exception: during the second registration exception should be throwing. The exception is only expected if we believe this is misuse of the framework; we don’t believe this to be true.
Overwrite: the overwrite could make sense, but the internal representation of the current implementation seems to imply it is not designed to overwrite due to the augmentation of the parameters for the mapTo type. In the example code below we are registering 2 different interfaces mapped to the same class and each of them inject 2 properties. We can see that the value of container.policies.policies( of type ObjectBuilder.SpecifiedPropertiesSelectorPolicy) propertiesAndValues , contains 4 injected properties. In the case of overwriting, we are expecting would expect to see 2 injected properties initialized with values from the second registration. Outcome of this behavior in case of registering several different types mapped to the same type and will inject in each of them some properties with values and some of them not (expecting to be not initialized) , the resolved instance will not have proper initialization of any registered types.
Independent registrations: all registration will be resolved properly , each of them will be injected with correct property values.
The independent registrations are what we expect, but does not work. It appears that the mapTo types are not managed based on the registered type but rather only on the mapTo type and the registered name. We would like to understand what the expected behavior is, and if the current behavior is expected, and if there is a clean way to achieve independent registrations.
Note that we have seen suggestions to name the registrations, but we don’t want to change our framework since it is in use, and generally we don’t want to force applications to conform to named instances for no logical reason.
The code attached demonstrates the unexpected behavior.
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
namespace TestUnity
{
public interface IBaseInterface
{
string BaseString { set; get; }
}
public interface IChildInterface : IBaseInterface
{
string ChildString { set; get; }
}
public class ChildClass : IChildInterface
{
public string BaseString { set; get; }
public string ChildString { set; get; }
}
public class ContainerClass
{
public IBaseInterface impl { set; get; }
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.LoadConfiguration();
// the expected result BaseString ="IBaseInterface_BaseString" & ChildString ="IBaseInterface_ChildString"
// the result is BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var iBaseInterface = container.Resolve<IBaseInterface>();
// the expected result BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var iChildInterface = container.Resolve<IChildInterface>();
//We expect test class will be initialize with BaseString ="IBaseInterface_BaseString" & ChildString ="IBaseInterface_ChildString"
//but the result is the expected result BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var testClass = container.Resolve<ContainerClass>("Test");
//The container.Registrations include both regestered types(IBaseInterface & IChildInterface)
foreach (var registration in container.Registrations)
{
Console.WriteLine(#"RegisteredType :{0} ,MappedToType :{1}", registration.RegisteredType, registration.MappedToType);
}
Console.ReadLine();
}
}
}
App.config
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IBaseInterface" type="TestUnity.IBaseInterface, TestUnity" />
<alias alias="IChildInterface" type="TestUnity.IChildInterface, TestUnity" />
<alias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity"/>
<container>
<register type="IBaseInterface" mapTo="TestUnity.ChildClass, TestUnity">
<lifetime type="transient"/>
<property name="BaseString" value="IBaseInterface_BaseString" />
<property name="ChildString" value="IBaseInterface_ChildString" />
</register>
<register type="IChildInterface" mapTo="TestUnity.ChildClass, TestUnity">
<lifetime type="transient" />
<property name="BaseString" value="IChildInterface_BaseString" />
<property name="ChildString" value="IChildInterface_ChildString" />
</register>
<register name="Test" type="TestUnity.ContainerClass, TestUnity" mapTo="TestUnity.ContainerClass, TestUnity">
<lifetime type="transient" />
<property name="impl" dependencyType="IBaseInterface" />
</register>
</container>
</unity>
</configuration>
TL;DR - Sorry, but this looks to be a limitation to Unity.
I'm not a member of the team that built Unity, so I can only speculate on the expected behavior as it is not explicitly documented for this specific scenario. But going by precedence with the other behaviors of Unity, I would have expected it to overwrite the previous registration's InjectionProperty.
You are correct that the object builder does not consider the registered type when looking up the policies for building up an instance of the object requested to be resolved. The object builder key is composed of the mapTo type and the name (see NamedTypeBuildKey). The way this key is created is integral to the internals of Unity's Object Builder. Attempting to add the registered type to this key in the pipeline would be much more customization than you would want to tackle. And I can't think of another way to introduce your desired behavior of independent registration based on the registered type (besides different concrete classes or multiple named registrations).
I am having difficulty configuring NLog using class name filters.
<rules>
<logger name="My.NameSpace.MyController" minlevel="Debug" writeTo="file" />
</rules>
It doesn't log if I specify a fully qualified class name, but it does work if I specify name="*"
I am using Castle Windsor to set this up:
Container.AddFacility<LoggingFacility>(f => f.UseNLog("NLog.config"));
Making this call in the MyController class
Logger = MvcApplication.Container.Resolve<ILogger>();
Is there anything else I have to specify to get this to work with the class rule?
I believe Castle Windsor replaces your class with a proxy and logger name you set in config does not match actual instance type.
You could explicitly set log's name like
Logger = LogManager.GetLogger("My.NameSpace.MyController").
Extra tip: in many cases resolving logger using inversion of control does not bring many benefits and you can avoid doing this, otherwise you should tweak up you logger registration in Castle Windsor.
If all classes under a given namespace use the same target, you can configure your rules like this:
<rules>
<logger name="MyApp.Controllers.*" minlevel="Debug" writeTo="fileTarget1" />
<logger name="MyApp.AnotherNamespace.*" minlevel="Debug" writeTo="fileTarget2" />
<logger name="*" minlevel="Error" writeTo="fileTarget3" />
</rules>
If you name your loggers with GetType().FullName in each controller (under MyApp.Controllers), the above configuration will write debug-level (and above) entries to fileTarget1, and error-level (and above) to both fileTarget1 and fileTarget3.
Bottomline, the * wildcard is tremendously useful when you don't know (or care about) the exact names of the types that will use a given logging rule, so in your case this would work for all classes under My.NameSpace:
<logger name="My.NameSpace.*" minlevel="Debug" writeTo="file" />
This works for me with Ninject, but as far as IoC is concerned it's just another dependency being injected, the container doesn't know it's a logging helper. So if Castle is generating the proxy AND you only need 1 target, you can probably get away with Castle.* as your filter.
If you are directly requesting an ILogger from the container (e.g with Logger = MvcApplication.Container.Resolve<ILogger>();) Windsor will always give you a default ILogger called Default.
You can change this default name with the ToLog method when configuring the LoggingFacility:
container.AddFacility<LoggingFacility>(f => f.UseNLog("NLog.config")
.ToLog("MyDefaultname"));
If you want to have the "current class logger" instead of a the default one then you need to let Windsor injects your ILogger instead of manually resolving it.
So if you using constructor injection:
public MyController
{
private ILogger logger;
public MyController(ILogger logger)
{
this.logger = logger;
}
}
or property injection:
public MyController
{
public ILogger Logger { get; set; }
}
Windsor will create an ILogger for you with the proper My.NameSpace.MyController name.
If you need more fine grained control of the logger names you can depend/resolve the Castle.Core.Logging.ILoggerFactory interface and you can create your own ILoggers with that.
I have two implementations of IEmailService, one for testing and one for live (is-A). And I have a BusinessService that has-A IEmailService reference.
BusinessService
IEmailService (has-A)
IEmailService
TestEmailService (is-A)
LiveEmailService (is-A)
In unity config, I register the two IEmailService implementations as follows.
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess"
name="Live">
<lifetime type="singleton" />
</register>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.TestEmailService, DataAccess"
name="Test">
<lifetime type="singleton" />
</register>
<container>
</unity>
Based on the appSetting for IEmailService I want Unity to pick the correct implementation. This will help while testing.
<appSettings>
<add key="IEmailService" value="Test"/>
</appSettings>
The issue is when unity resolves BusinessService, it tries to resolve (none) named mapping of IEmailService instead of Live or Test and throws an ResolutionFailedException.
container.Resolve<BusinessService>(); throws below exception:
BusinessServices.Test.BusinessServiceTest_Integration.Test103:
Microsoft.Practices.Unity.ResolutionFailedException : Resolution of the dependency failed, type = "BusinessServices.BusinessService", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:
Resolving BusinessServices.BusinessService,(none)
Resolving parameter "emailService" of constructor BusinessServices.BusinessService(DataAccess.IEmailService emailService)
Resolving DataAccess.IEmailService,(none)
----> System.InvalidOperationException : The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?
The workaround I came up with is to specify the registrations in code as well and have a wrapper method around container.RegisterType to register IEmailService with (none) named mapping as well based on the appSetting value.
IUnityContainer container;
// registering unity
static void Load()
{
container = new UnityContainer().LoadConfiguration();
RegisterType<IEmailService, TestEmailService>("Test");
RegisterType<IEmailService, LiveEmailService>("Live");
}
// register the `Test` or `Live` implementation with `(none)` named mapping as per appSetting
static void RegisterType<TFrom, TTo>(string name)
where TTo : TFrom
{
var tFromAppSetting= ConfigurationManager.AppSettings[typeof(TFrom).Name];
if (!string.IsNullOrEmpty(tFromAppSetting) && tFromAppSetting == name)
container.RegisterType<TFrom, TTo>();
}
This works, but I end up specifying the registrations in two places - config as well as code. Is there a better way for doing this?
Update
I actually had got it correct by code. I do not need the unity config at all. The RegisterType<TFrom, TTo>(string name) registers either the Test or Live implementation as (none) named mapping depending on appSetting value. BusinessService is also resolved without exception.
As there is no unity config, I do not have load the configuration.
container = new UnityContainer();
In my opinion the only point of having registrations in config is to not have them in code and being able to replace implementation without recompilation. So you are write in trying to remove it form code. What I don't understand is why you want to have both registrations in config in the first place. Simply remove the Live one from config for tests and the Test from config for application and register them both without name.
So for instance in application app.config:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess">
<lifetime type="singleton" />
</register>
Since you really are determent to do it your way:
The other way around this is to register in code only a way of determining which instance is the default one:
container.RegisterType<IEmailService>(new InjectionFactory((c)=>
{
var name = GetImplementationsNameFromAppSettings();
return c.Resolve<IEmailService>(name);
});