I'm using Patterns and Practices' Unity to inject dependencies into my objects and have hit a weird (to me, anyway) issue. Here's my class definitions:
public class ImageManager : IImageManager
{
IImageFileManager fileManager;
public ImageManager(IImageFileManager fileMgr)
{
this.fileManager = fileMgr;
}
}
public class ImageFileManager : IImageFileManager
{
public ImageFileManager(string folder)
{
FileFolder = folder;
}
}
And here's the code to register my classes
container.RegisterInstance<MainWindowViewModel>(new MainWindowViewModel())
.RegisterType<IPieceImageManager, PieceImageManager>(
new InjectionConstructor(typeof(string)))
.RegisterType<IImageFileManager, ImageFileManager>()
.RegisterType<IImageManager, ImageManager>(
new InjectionConstructor(typeof(IImageFileManager)));
I originally resolved this in the code behind (I know, it defeats the purpose. Bear with me.) of the XAML file like this
IImageManager imageManager = MvvmViewModelLocator.Container.Resolve<IImageManager>(
new ParameterOverride("folder", "/images"));
And it worked. But I created a view model for my main view and when I copied the same line into it, I get an exception. Here are the two most inner exceptions:
InnerException: Microsoft.Practices.Unity.ResolutionFailedException
HResult=-2146233088
Message=Resolution of the dependency failed, type = "SwapPuzzleApp.Model.IImageManager", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type IImageManager does not have an accessible constructor.
At the time of the exception, the container was:
Resolving SwapPuzzleApp.Model.IImageManager,(none)
Source=Microsoft.Practices.Unity
TypeRequested=IImageManager
StackTrace:
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides)
at SwapPuzzleApp.ViewModel.MainWindowViewModel..ctor() in c:\Users\Carole\Documents\Visual Studio 2012\Projects\SwapPuzzle\SwapPuzzle\ViewModel\MainWindowViewModel.cs:line 17
at SwapPuzzleApp.ViewModel.MvvmViewModelLocator..cctor() in c:\Users\Carole\Documents\Visual Studio 2012\Projects\SwapPuzzle\SwapPuzzle\ViewModel\MvvmViewModelLocator.cs:line 51
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=The type IImageManager does not have an accessible constructor.
Source=Microsoft.Practices.Unity
StackTrace:
StackTrace:
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
InnerException:
I'm not sure what the problem is, as ImageManager clearly has a public constructor. I thought it might be due to an invalid path, but if I concretely instantiate the object, everything works.
// this line has no problems
IImageManager imageManager = new ImageManager(new ImageFileManager("/images"));
I also wondered if I needed to pass in new InjectionConstructor(typeof(string)) when I register IImageManager, but it doesn't seem to help and why would it be needed now and not before? So I'm stumped. This is my first attempt at using Dependency Injection, so it's probably something basic. I'm just not seeing what, though.
Look very closely at the error message. Notice this part:
Message=The type IImageManager does not have an accessible constructor.
Notice the type name is IImageManager, not ImageManager. Somewhere along the line you lost your type mapping.
Your registration of FileImageManager has a problem as well, since you don't specify the folder parameter in the registration, so Unity has no idea what string to pass.
I was using the examples in this article as my guide. Either the examples in there are way too advanced for an introduction, or there's misinformation in that topic.
After consulting other sources (mainly PluarlSight), I came up with a much simpler and more logical solution.
container.RegisterInstance<TimerViewModel>(new TimerViewModel());
container.RegisterType<IPieceImageManager, PieceImageManager>();
container.RegisterType<IImageFileManager, ImageFileManager>
(new InjectionConstructor("/images"));
container.RegisterType<IImageManager, ImageManager>();
I ran into a similar issue with this error tied directly to a Mock (using automoq) that I was doing for an operation. In this case it turned out that because there were a number of member methods that get called with the object being mocked, that I had to define all of those in the automoq chain to get it to resolve properly
I realize this is an example in instance code, but it could occur in Moqs also. So if you read this and are wondering about an example related to Moqs, look into that first.
Related
Below code is to Initialize Dependency Injection Container in application global.asax
IUnityContainer container = new UnityContainerFactory().CreateConfiguredContainer();
var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
But application is always failing with parameter less constructor exception for
HomeController, below is the exception.
Resolution of the dependency failed, type = "MyApp.Web.Controllers.HomeController", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Microsoft.Practices.ServiceLocation.IServiceLocator, is an interface and cannot be constructed. Are you missing a type mapping?
At the time of the exception, the container was:
Resolving MyApp.Web.Controllers.HomeController,(none)
Resolving parameter "serviceLocator" of constructor MyApp.Web.Controllers.HomeController(Microsoft.Practices.ServiceLocation.IServiceLocator serviceLocator)
Resolving Microsoft.Practices.ServiceLocation.IServiceLocator,(none)
Below is the inner exception of the exception.
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs:line 207
at BuildUp_Microsoft.Practices.ServiceLocation.IServiceLocator(IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\BuildPlanStrategy.cs:line 43
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\StrategyChain.cs:line 112
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 215
at BuildUp_MyApp.Web.Controllers.HomeController(IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\BuildPlanStrategy.cs:line 43
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\StrategyChain.cs:line 112
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:line 511
Microsoft.Practices.Unity 2.0.414.0 has been used. What is the issue with implementation, am I missing something?
You need to register all interfaces your controller relies on. In this case
HomeController(Microsoft.Practices.ServiceLocation.IServiceLocator serviceLocator) {...}
Means you need to have line like
container.RegisterType<IServiceLocator, SomeServiceLocatorImpl>();
Note that it is generally better practice to depend on required interfaces instead on IServiceLocator - How to avoid Service Locator Anti-Pattern?
Your constructor presumably has the following signature
public class HomeController : Controller
{
public HomeController( IServiceLocator locator )
{
...
Unity follows the signature and tries to find a concrete type mapped to the interface, registered in your container. But there is none.
What you do however, is a mistake. You should be injecting actual dependencies to services / business objects, not to the infrastructure class a service locator is.
public HomeController( ISomeService service, IAnotherService another )
Unity would resolve these, assuming you first map abstractions to concrete types.
I'm using Entity Framework 6 and want to unit test some of my business logic code. Following Microsoft's example on how to do this, they provide the following example using MOQ:
var mockSet = new Mock<DbSet<Blog>>();
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
I'm using FakeItEasy instead of MOQ, and I'd hoped it would be just as simple, however FakeItEasy complains that it can't create a fake of my DbSet using the following:
var fakeDbSet = A.Fake<DbSet<InstalledProduct>>();
I get an exception as follows:
FakeItEasy.Core.FakeCreationException: Failed to create fake of
type "TN.Prs.Persistence.LicenseContext".
Below is a list of reasons for failure per attempted constructor:
No constructor arguments failed:
No usable default constructor was found on the type TN.Prs.Persistence.LicenseContext.
An exception was caught during this call. Its message was:
Access is denied: 'TN.Prs.Persistence.LicenseContext'.
at
FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithResolvedConstructors(Type
typeOfFake, String reasonForFailureOfUnspecifiedConstructor,
IEnumerable1 resolvedConstructors) at
FakeItEasy.Creation.FakeObjectCreator.TryCreateFakeWithDummyArgumentsForConstructor(Type
typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession
session, String failReasonForDefaultConstructor, Boolean
throwOnFailure) at
FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake,
FakeOptions fakeOptions, IDummyValueCreationSession session, Boolean
throwOnFailure) at
FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type
typeOfFake, FakeOptions options) at
FakeItEasy.Creation.DefaultFakeCreatorFacade.CreateFake[T](Action1
options) at FakeItEasy.A.FakeT at
TN.Prs.RegistrationServices.Specifications.when_activating_a_product_from_a_valid_digitally_signed_activation_key.<.ctor>b__0()
in
My POCO classes are internal rather than public, but I've added the InternalsVisibleTo attributes as appropriate, for DynamicProxyGenAssembly2. When I make the classes public, everything works, but I really don't want to expose these classes publicly. I would appreciate any suggestions.
Here is my context class:
internal class LicenseContext : DbContext
{
public LicenseContext()
{
}
public virtual DbSet<InstalledProduct> ManagedProducts { get; set; }
}
Problem solved!
Before I added the InternalsVisibleTo attributes, FakeItEasy complained and told me to add those attributes and I was delighted to see that it gave me the exact code I needed right in the error message. I even remarked to one of my colleagues, "now THAT is what I call an error message!". The attribute it suggested was:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
Unfortunately that doesn't work and I get an 'Access Denied' error. It might be that the public key isn't correct, but since my assemblies are not strong-named, I simply removed the public key from the attributes and everything works.
Eventually I will have to strong-name my assemblies so I will have to solve this public key problem eventually, but I know what to do so it shouldn't be an obstacle.
The following is error I am getting. Please help on this.
Telerik.OpenAccess.OpenAccessException was unhandled by user code
Message=No metadata has been registered for class Ind.Data.IndiStage.Academy. (This usually indicates, that either this class is not declared persistent or it is declared persistent but not enhanced. The class was loaded from file:///C:/Users/suresh/Documents/WorkSpace/Ind_folder/Ind.ETLService/bin/Release/Ind.Data.IndiStage.DLL.)
Source=Telerik.OpenAccess
CanRetry=true
StackTrace:
at Telerik.OpenAccess.SPI.Backends.ThrowException(Exception e)
at OpenAccessRuntime.ExceptionWrapper.Throw()
at OpenAccessRuntime.storagemanager.StorageManagerFactoryBuilder.createSmfForURL()
at OpenAccessRuntime.storagemanager.StorageManagerFactoryBuilder.createStorageManagerFactory()
at OpenAccessRuntime.DataObjects.PersistenceManagerFactoryImp.createStorageManagerFactory()
at OpenAccessRuntime.DataObjects.PersistenceManagerFactoryBase.init()
at OpenAccessRuntime.DataObjects.PersistenceManagerFactoryImp.init()
at OpenAccessRuntime.DataObjects.PersistenceManagerFactoryImp..ctor(PropertySet properties, Object classloader)
at OpenAccessRuntime.DataObjects.PersistenceManagerFactoryImp.getPersistenceManagerFactory(PropertySet props)
at OpenAccessRuntime.DataObjects.BootstrapPMF.getPersistenceManagerFactory(PropertySet props)
at OpenAccessRuntime.Helper.getPersistenceManagerFactory(PropertySet props)
at OpenAccessRuntime.DatabaseAdapter.AssertPersistenceManagerFactory(String usr, String password, Boolean open)
at OpenAccessRuntime.DatabaseAdapter.GetObjectScope(TransactionProvider provider)
at Telerik.OpenAccess.Database.GetObjectScope(TransactionProvider provider)
at Telerik.OpenAccess.OpenAccessContextBase.GetScope()
at Telerik.OpenAccess.OpenAccessContext.GetAllCore[T]()
at Telerik.OpenAccess.OpenAccessContext.GetAll[T]()
at System.Timers.Timer.MyTimerCallback(Object state)
InnerException:
wow.
I got a hardtime to get rid of this exception. "No metadata has been registered for class" with Telerik OpenAccess.
read this article especially you use CI build system like TeamCity: http://docs.telerik.com/data-access/developers-guide/integrating-data-access-in-your-solution/external-tools-howto-integrate-enhancer-msbuild
I'm having problems resolving a repository when calling it from a console app. Everything works fine when running the application (.NET 4, C#, Entity Framework, Unity) as normal, but I've created a standalone console app that will be run from the task scheduler to import feeds. I'm very close to giving up and do a dirty hack and write a script to call a webpage instead of using a console app, but I thought I'd at least try to understand why it isn't working first.
I'm new to both Entity Framework and Unity, so please bear with me and let me know if I've left out any important information.
This is the error I'm getting:
Resolution of the dependency failed, type = "MyNamespace.Domain.Template.IRepository`2[MyNamespace.Domain.Employees.OrganisationalUnit,System.Guid]", name = "(none)".
Exception occurred while: while resolving.
Exception is: NullReferenceException - Object reference not set to an instance of an object.
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides)
at MyNamespace.Infrastructure.FeedDefinition.GetOrganisationalUnit(String name, OrganisationalUnit parent) in C:\FeedDefinition.cs:line 552
This is the console app code:
static void Main(string[] args)
{
if (args.Length > 0)
{
MyNamespace.Appliance.Configuration.Initialise.InitialiseContainer();
ImportFeedProcessor importFeedProcessor = new ImportFeedProcessor();
importFeedProcessor.Run(args[0]);
}
}
And this is where it fails:
IRepository<OrganisationalUnit, Guid> organisationalUnitRepository =
Context.Instance.Container.Resolve<IRepository<OrganisationalUnit, Guid>>();
If anyone can help me understand what's going wrong I'd be very grateful!
UPDATE:
Here's the (important) bits from the initialise class:
public static void InitialiseContainer()
{
UnityContainer container = new UnityContainer();
// Use HttpContext for registering instances against for live
IContext context = HttpContextWrapper.Instance;
// Register the HttpContext as the default context to use
container.RegisterInstance<IContext>(HttpContextWrapper.Instance);
// repositories
container.RegisterType<IRepository<Employee, Guid>, EmployeeRepository>(
new UnityContextLifetimeManager(context),
new InjectionConstructor(true, "OrganisationalUnit.Parent.Parent"));
container.RegisterType<IRepository<OrganisationalUnit, Guid>, EntityFrameworkRepository<OrganisationalUnit, Guid>>(
new UnityContextLifetimeManager(context),
new InjectionConstructor("Parent.Parent"));
// Create and populate a new Unity container from configuration
Context.Instance.Container = container;
}
Is it perhaps the HttpContext that does it?
Thanks,
Annelie
One option you could consider is creating two different Initialise classes (I'm guessing that is your Unity bootstrapper class).
The one you have can be used for your web application.
The other one should be non-web specific. Remove any reference to HttpContext (it won't be available in a Console app) and UnityContextLifetimeManager (assuming this is HttpContext specific as well).
I am getting error "An item with the same key has already been added." I get this error randomly when many user try to access the same page on site in production at the same time.
In the code docid is passed and relevant help is displayed to user. As each user is viewing the same page so same ID is passed for all users. There is no insert operation in this call
Stack trace and souce code of mentioned line is given as follows
public string DocDescription(int docid)
{
DocumentRepository _Documentrepository = new DocumentRepository();
return _Documentrepository.GetDocDescription(docid);
}
}
public string GetDocDescription(int DocID)
{
if (DocID != 0)
return db.sysDocuments.SingleOrDefault(p => p.DocumentID == DocID).Description==null?"No Description Available":db.sysDocuments.SingleOrDefault(p => p.DocumentID == DocID).Description;
else
return "No Description Available";
}
Stack Trace excerpt:
System.Web.HttpException (0x80004005): Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerWrapper'. ---> System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.Web.HttpException (0x80004005): Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'. ---> System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Data.Linq.DataContext.GetTable(MetaTable metaTable)
at System.Data.Linq.DataContext.GetTable[TEntity]()
at UserManagement.Models.DocumentRepository.GetDocDescription(Int32 DocID) in D:\Myproj\UserManagement\UserManagement\Models\DocumnetRepository.cs:line 109
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at Castle.Proxies.ControllerActionInvokerProxy.InvokeActionMethod_callback(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at Castle.Proxies.Invocations.ControllerActionInvoker_InvokeActionMethod.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Net.Interceptor.InvokeActionMethodInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
From your code and comments, I get that you store db context in a static variable. This is generally a bad idea when working with entities.
DbContext is not thread safe. So, multiple users working with your site will cause such errors in context.
The general suggestion for working with context is to prefer short lived context. So just create a new instance, when you need it, and then forget it. For the web sites, it is quite common to use inversion of control container like Unity, Castle.Winsdor etc, and configure it to return one instance per web request for your DbContext. This will give you enough performance, so all entities needed for the current request are cached, and will not cause threading issues at the same time.
See comment too, static members are application scoped variables thus they're sharing the same dictionary which can throw errors like this if multiple requests add the same key.