简体   繁体   中英

Ninject.ActivationException was unhandled by user code

I'm stuck on this problem for the last 2 days, what I want to do is prevent creating an instance of DisplayWeatherAstronomy, I thought it was fixed last night with the help of Tadmas on another thread, but I ran into a problem with Ninject.

So I modified my code and turned my class into an abstract class using an interface, but I'm still getting problems with Ninject and I have no idea how to fix it, even though the error looks pretty self explanatory.

My error is:

Ninject.ActivationException was unhandled by user code
  HResult=-2146233088
  Message=Error activating IDisplayWeatherAstronomy using binding from IDisplayWeatherAstronomy to GetWeatherAstronomyData
No constructor was available to create an instance of the implementation type.

Activation path:
  2) Injection of dependency IDisplayWeatherAstronomy into parameter igwa of constructor of type WeatherController
  1) Request for WeatherController

Suggestions:
  1) Ensure that the implementation type has a public constructor.
  2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.

  Source=Ninject
  StackTrace:
       at Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 82
       at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 157
       at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
       at Ninject.Planning.Targets.Target`1.GetValue(Type service, IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 197
       at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 165
       at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 114
       at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96
       at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
       at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
       at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
       at Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96
       at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 157
       at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
       at Ninject.Web.Mvc.NinjectDependencyResolver.GetService(Type serviceType) in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectDependencyResolver.cs:line 56
       at Castle.Proxies.Invocations.IDependencyResolver_GetService.InvokeMethodOnTarget()
       at Castle.DynamicProxy.AbstractInvocation.Proceed()
       at Glimpse.Core.Extensibility.CastleInvocationToAlternateMethodContextAdapter.Proceed()
       at Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult)
       at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
       at Glimpse.Core.Extensibility.AlternateTypeToCastleInterceptorAdapter.Intercept(IInvocation invocation)
       at Castle.DynamicProxy.AbstractInvocation.Proceed()
       at Castle.Proxies.IDependencyResolverProxy.GetService(Type serviceType)
       at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
  InnerException: 

Code:

public abstract class GetWeatherAstronomyData : IDisplayWeatherAstronomy
    {
        public class DisplayWeatherAstronomy
        {
            public string SunRise { get; internal set; }
            public string SunSet { get; internal set; }
            public string MoonRise { get; internal set; }
            public string MoonSet { get; internal set; }
        }

        public IEnumerable<DisplayWeatherAstronomy> WeatherAstronomy(string id)
        {
            var doc = WeatherForcast.WeatherLocationSearchXmlDataAsync(id);
            var result = XDocument.Parse(doc.Result);
            var displayAstronomy = (from wd in result.Descendants("astronomy")
                                    select new DisplayWeatherAstronomy
                                    {
                                        SunRise = (string)wd.Element("sunrise") ?? string.Empty,
                                        SunSet = (string)wd.Element("sunset") ?? string.Empty
                                    });

            return displayAstronomy;
        }
    }

Interface

public interface IDisplayWeatherAstronomy
    {
        IEnumerable<GetWeatherAstronomyData.DisplayWeatherAstronomy> WeatherAstronomy(string id);
    }

Ninject

private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IDisplayWeatherAstronomy>()
                .To<GetWeatherAstronomyData>()
                .InSingletonScope();
        }  

Finally Controller

private readonly IDisplayWeatherAstronomy _igwa;
        public WeatherController(IDisplayWeatherAstronomy igwa)
        {
            _igwa = igwa;
        } 

Any help in finally solving this problem would be appreciated

George

You cannot instantiate an abstract class. Ninject can't do that either. Remove the abstract modifier from GetWeatherAstronomyData .

If you want to prevent your class from being instantiated by someone else, put it, along with the interface, in an "extra" project / assembly B and make it internal , not public (not abstract , either!). The interface must be public .

Then also add a ninject Module to the same assembly, which creates the binding:

public class WeatherModule : NinjectModule
{
  this.Bind<IDisplayWeatherAstronomy>().To<DisplayWeatherAstronomy>();
}

Then, in your original project, add a reference to project / assembly B and load the WeatherModule :

kernel.Load<WeatherModule>();

That's it.

But keep in mind that still anyone can create the class by using

IResolutionRoot.Get<IDisplayWeatherAstronomy>();

so you only gain something if you can restrict access to the kernel, which is most often unpractical.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM