Sometimes I get this error stack trace at my web app:
[ArgumentException: An item with the same key has already been added.]
System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +52
System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +10695474
System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) +10
NHibernate.Util.ThreadSafeDictionary`2.Add(TKey key, TValue value) +93
NHibernate.Type.TypeFactory.GetType(NullableType defaultUnqualifiedType, Int32 length, GetNullableTypeWithLength ctorDelegate) +88
NHibernate.Type.TypeFactory.<RegisterDefaultNetTypes>b__c(Int32 l) +82
NHibernate.Type.TypeFactory.BuiltInType(String typeName, Int32 length) +46
NHibernate.Mapping.SimpleValue.GetHeuristicType() +168
NHibernate.Mapping.SimpleValue.get_Type() +49
NHibernate.Mapping.SimpleValue.IsValid(IMapping mapping) +30
NHibernate.Mapping.PersistentClass.Validate(IMapping mapping) +87
NHibernate.Mapping.RootClass.Validate(IMapping mapping) +21
NHibernate.Cfg.Configuration.ValidateEntities() +183
NHibernate.Cfg.Configuration.Validate() +13
NHibernate.Cfg.Configuration.BuildSessionFactory() +36
Framework.Data.Code.BaseSessionFactoryProvider..ctor() +74
Framework.Data.Code.SessionFactoryProvider..ctor() +29
Framework.Data.Code.NestedSessionManager..cctor() +43
My SessionFactoryProvider is thread-safe singletone:
public interface ISessionFactoryProvider
{
ISessionFactory GetSessionFactory();
}
public abstract class BaseSessionFactoryProvider : ISessionFactoryProvider
{
protected readonly ISessionFactory factory;
public ISessionFactory GetSessionFactory()
{
return factory;
}
protected BaseSessionFactoryProvider()
{
factory = GetConfig().BuildSessionFactory();
}
public abstract Configuration GetConfig();
}
public class SessionFactoryProvider : BaseSessionFactoryProvider
{
public static ISessionFactory SessionFactory
{
get { return Instance.factory; }
}
public override Configuration GetConfig()
{
return new Configuration().Configure();
}
public static SessionFactoryProvider Instance
{
get
{
return NestedSessionManager.sessionManager;
}
}
class NestedSessionManager
{
internal static readonly SessionFactoryProvider sessionManager =
new SessionFactoryProvider();
}
}
Also in my app I bind SessionFactoryProvider to ISessionFactoryProvider via ninject
kernel.Bind<ISessionFactoryProvider>().To<SessionFactoryProvider>().InSingletonScope();
So my question why do i get this error?
In my comments, I said I saw no flaw in your Singleton implementation.
In fact, there is an obvious one : your SessionFactoryProvider parameterless constructor is not private, because SessionFactoryProvider does not have any overload for its constructor.
So the compiler generates a public parameterless constructor for SessionFactoryProvider
see Should we always include a default constructor in the class?
So any code can instantiate a new SessionFactoryProvider through
this public constructor (this should be easy to test) which is used by Ninject to instantiate the class. (This was the point that puzzled me : how does Ninject instantiate the class ? It should not be able to instantiate a class without public constructor).
I guess this is how you end-up with duplicate SessionFactoryProvider.
You should implement your SessionFactoryProvider with a public constructor, leaving out any consideration of singleton implementation. Then just rely on Ninject and its InSingletonScope() to provide singleton functionnality
Related
I am able to serialize proxy objects using below code:
public class NHibernateContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType))
return base.CreateContract(objectType.BaseType);
return base.CreateContract(objectType);
}
}
But how can I make JSON.NET ignore the NHibernate Proxy objects during serialization.
The problem I am facing is that, the parent object is fetching 1000's of child object, where as I want to send JSON only for the parent object, so I want to ignore proxy object and fetch only eager loaded relationships.
And if I comment above code, then I get the error for JSON.NET failing to serialize the proxy objects.
Please help!
write a dummy class like this.
public class NhProxyJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteNull();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return typeof(INHibernateProxy).IsAssignableFrom(objectType);
}
}
I have a view model class which uses UnitOfWork to some database operations like fetching of items to create select lists and IPrincipal for some auditing (like modified by etc.). It cannot work without this UOW. I have configured my web site to use Ninject to inject UOW into Controllers. From controller I pass this UOW when creating view model. But when performing POST operation I am getting
No parameterless constructor defined for this object.
I have few SelectList type of properties which I have excluded with Bind attribute.
How can I overcome this problem? Can I configure Ninject to create the objects of this type and make ModelBinder use it?
Perhaps inheriting from DefaultModelBinder and resolving the model classes via Ninject?
Update:
NinjectModelBinder.cs
public class NinjectModelBinder : DefaultModelBinder
{
private readonly StandardKernel _kernel;
public NinjectModelBinder(StandardKernel kernel)
{
_kernel = kernel;
}
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext, Type modelType)
{
var model = _kernel.TryGet(modelType);
if (model != null) return model;
return base.CreateModel(controllerContext, bindingContext, modelType);
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
var kernel = new StandardKernel();
ModelBinders.Binders.DefaultBinder = new NinjectModelBinder(kernel);
}
}
I am pretty new to castle and Ninject . how ever i have a statement where an Interface is initialised as factory method as like this
public class LazySessionContext
{
private readonly ISessionFactoryImplementor factory;
private const string CurrentSessionContextKey = "NHibernateCurrentSession";
public LazySessionContext(ISessionFactoryImplementor factory)
{
this.factory = factory;
}
}
Now when injecting ISessionFactoryImplementor as factory method we have done like this
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<ISessionFactoryProvider>().AsFactory());
container.Register(Component.For<IEnumerable<ISessionFactory>>()
.UsingFactoryMethod(k => k.ResolveAll<ISessionFactory>()));
}
can someone please mention how to achieve the same in ninject ? so as the ISessionFactoryProvider is provided and initialised as a factory method in ninject ?
kernel.Bind<ISessionFactoryProvider>().ToFactory();
is the equivalent. to this configuration. You have to use Ninject.Extensions.Factory. The IEnumerable configuration exists by default.
I have a problem with Ninject trying to resolve an interface type where the concrete type derives from an abstract base class that implements the interface.
EDIT: This is on Windows Mobile using .NET CF.
My particular issue involves presenters and views, so I stick to that in this example instead of foos and bars.
I want to inject factories for presenters and views to allow for late creation of those instances deep down the UI view stack.
Below I've omitted all error checking for better readability.
My factory interface:
public interface IFactory<T>
{
T Create();
}
My presenter and view:
public sealed class Presenter
{
private readonly View view;
public Presenter(View view)
{
this.view = view;
}
}
public sealed class View
{
public View()
{
}
}
First, I'll show what works perfectly, that Ninject resolves as expected. This will not include the abstract base class I mentioned at the beginning. After this, I'll add the slight modifications with the abstract base class that will make Ninject throw when trying to resolve the dependencies.
We see above that the presenter depends on the view, so the presenter factory will depend on the view factory:
public sealed class GoodPresenterFactory : IFactory<Presenter>
{
private readonly IFactory<View> viewFactory;
public GoodPresenterFactory(IFactory<View> viewFactory)
{
this.viewFactory = viewFactory;
}
public Presenter Create()
{
return new Presenter(this.viewFactory.Create());
}
}
public sealed class ViewFactory : IFactory<View>
{
public ViewFactory()
{
}
public View Create()
{
return new View();
}
}
Wiring this up with Ninject:
Bind<IFactory<Presenter>>().To<GoodPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();
And then resolving the presenter factory:
var presenterFactory = container.Get<IFactory<Presenter>>();
Everything up until now works perfectly. The dependency on the view factory inside the presenter factory is resolved as expected.
Now, I have a million classes that looks like GoodPresenterFactory above and I therefore wanted a small base class to handle some trivial common stuff, like the dependency on the view factory in the presenter factory:
public abstract class FactoryBase<T, U> : IFactory<T>
{
protected readonly U dependency;
protected FactoryBase(U dependency)
{
this.dependency = dependency;
}
public abstract T Create();
}
Then the presenter factory will change and something in that change will make Ninject fail resolving:
public sealed class BadPresenterFactory : FactoryBase<Presenter, IFactory<View>>
{
public BadPresenterFactory(IFactory<View> viewFactory)
: base(viewFactory)
{
}
public override Presenter Create()
{
return new Presenter(this.dependency.Create());
}
}
And changing the Ninject wiring accordingly:
Bind<IFactory<Presenter>>().To<BadPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();
Those changes will make Ninject throw an ArgumentNullException when doing
var presenterFactory = container.Get<IFactory<Presenter>>();
Call stack from the exception:
at System.Reflection.RuntimeMethodInfo.GetParentDefinition()
at System.Reflection.CustomAttribute.IsDefined(MemberInfo member, Type caType, Boolean inherit)
at System.Reflection.RuntimeMethodInfo.IsDefined(Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType)
at Ninject.Infrastructure.Language.ExtensionsForMemberInfo.HasAttribute(MemberInfo member, Type type)
at Ninject.Selection.Heuristics.StandardInjectionHeuristic.ShouldInject(MemberInfo member)
at Ninject.Selection.Selector.<>c__DisplayClassa.<SelectMethodsForInjection>b__9(IInjectionHeuristic h)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
at Ninject.Selection.Selector.<SelectMethodsForInjection>b__8(MethodInfo m)
at System.Linq.Enumerable.<WhereIterator>d__0`1.MoveNext()
at Ninject.Planning.Strategies.MethodReflectionStrategy.Execute(IPlan plan)
at Ninject.Planning.Planner.<>c__DisplayClass2.<GetPlan>b__0(IPlanningStrategy s)
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
at Ninject.Planning.Planner.GetPlan(Type type)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<Resolve>b__4(IContext context)
at System.Linq.Enumerable.<SelectIterator>d__d`2.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b0`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
at NinjectTest.Program.Main()
If I modify FactoryBase so that it has no dependency, it's just a naked base class, then Ninject also fails.
public abstract class NakedFactoryBase<T> : IFactory<T>
{
protected NakedFactoryBase()
{
}
public abstract T Create();
}
public sealed class PointlessPresenterFactory : NakedFactoryBase<Presenter>
{
private readonly IFactory<View> viewFactory;
public PointlessPresenterFactory(IFactory<View> viewFactory)
{
this.viewFactory = viewFactory;
}
public override Presenter Create()
{
return new Presenter(this.viewFactory.Create());
}
}
As you can see, that failing PointlessPresenterFactory is identical to the succeeding GoodPresenterFactory, apart from the direct IFactory<Presenter> implementation in GoodPresenterFactory, as opposed to the completeley naked base class used in PointlessPresenterFactory.
Any idea why Ninject fails to resolve when the factory base class is used?
This issue has been fixed in build 2.3.0.46 and will be part of the next release (2.4).
NOTE: because CF seems not to allow to detect is a method is generic or not the Inject attribute can not be defined on base methods anymore. It has to be defined on the overload method.
In my MVC project, I have setup my MvcApplication_start() :
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
And have successfully bound an .To regarding my IProductsRepository to MySqlProductsRepository:
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel = new StandardKernel(new MyServices());
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController) _kernel.Get(controllerType);
}
public class MyServices: NinjectModule
{
public override void Load()
{
Bind<IProductsRepository>().To<MySqlProductsRepository>();
}
}
}
But I am using NHibernate, and have a separate Session Factory class that has a GetSession() method that returns an ISession.
public static ISessionFactory SessionFactory = CreateSessionFactory();
private static ISessionFactory CreateSessionFactory()
{
var cfg = new Configuration().Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nhibernate.config"));
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName, System.Environment.MachineName);
NHibernateProfiler.Initialize();
return cfg.BuildSessionFactory();
}
public static ISession GetSession()
{
return SessionFactory.GetCurrentSession();
}
I wanted to set it up so that my MySqlProductsRepository would be passed and ISession object by Ninject when it was created:
public class MySqlProductsRepository : IProductsRepository
{
private readonly ISession _session;
public MySqlProductsRepository(ISession session)
{
_session = session;
}
And my Controller would be handed a IProductsRepository instance:
public class AdminController : Controller
{
private readonly IProductsRepository _productsRepository;
public AdminController(IProductsRepository productsRepository)
{
_productsRepository = productsRepository;
}
MY PROBLEM:
I can't seem to figure out in my IoC container where I bind my IProductsRepository to my Repository, how to register an ISession, how to hand an ISession to my MyProductsRepository object when it is created, and hand an MyProductsRepository object to my Controller?
I have a couple of blog post I wrote that explain how to use Ninject in and ASP.NET MVC application. The application in the blog post uses the same technologies that you are using: Ninject, NHibernate, and MySql. I also am using a repository pattern. There are a lot of parallels between what you are doing and these posts.
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
Take a look. If you have questions, feel free to contact me.