依赖注入 - 当前上下文中不存在名称为“Bind”的内容 - MethodAccessException未处理

3

示例代码:

namespace DependencyInjection
{
class Program  
{
    static void Main(string[] args)
    {
        IKernel kernel = new StandardKernel();
        var samurai = kernel.Get<Samurai>();
        Bind<IWeapon>().To<Sword>();
   }       
}



class Samurai
{
    readonly IWeapon _weapon;
    public Samurai(IWeapon weapon)
    {
        _weapon = weapon;
    }
    public void Attack(string target)
    {
        _weapon.Hit(target);
    }
}

interface IWeapon
{
    void Hit(string target);
}

class Sword : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Sword - ", target);
    }
}

class Arrow : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Arrow - ", target);
    }
}
}

这是我第一次尝试使用ninject实现DI。
我不确定如何解决错误“The name 'Bind' does not exist in the current context”。我查看了这个问题 Compilation Error with Ninject,但仍然不确定如何解决。如何解决这个问题?如果能提供代码示例,那就太好了,这样我就能更好地理解。
namespace DependencyInjection
{
class Program  
{
    static void Main(string[] args)
    {
        IKernel kernel = new StandardKernel();
        kernel.Bind<IWeapon>().To<Sword>();
        var samurai = kernel.Get<Samurai>(); -----> Exception Line
        samurai.Attack("Hello");
   }       
}

class Samurai
{
    readonly IWeapon _weapon;
    public Samurai(IWeapon weapon)
    {
        _weapon = weapon;
    }
    public void Attack(string target)
    {
        _weapon.Hit(target);
    }
}

interface IWeapon
{
    void Hit(string target);
}

class Sword : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Sword - ", target);
    }
}

class Arrow : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Arrow - ", target);
    }
}
}

上面的代码会在 var samurai = kernel.Get(); 这一行出现 "MethodAccessException was unhandled" 异常。我在谷歌上搜索,但并没有找到任何具体的解决方案。 异常信息
System.MethodAccessException was unhandled
  Message="DependencyInjection.Sword..ctor()"
  Source="Anonymously Hosted DynamicMethods Assembly"
  StackTrace:
       at DynamicInjector84db385a6cfb4301b146100b5027c44a(Object[] )
       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.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
       at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
       at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
       at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass1.<Create>b__0(ITarget target)
       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)
       at Ninject.Activation.Context.Resolve()
       at Ninject.KernelBase.<Resolve>b__4(IContext context)
       at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.<CastIterator>d__aa`1.MoveNext()
       at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
       at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
       at DependencyInjection.Program.Main(String[] args) in D:\Sandboxes\C_Sharp\DependencyInjection\DependencyInjection\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

你可以通过使用Autofac来解决这个问题 :) - bentayloruk
@bentayloruk:你真的认为Ninject有那样的bug吗? - Mauricio Scheffer
@mauricio-scheffer 不,我从未使用过Ninject。我希望这个笑容能表明这是一个玩笑。 - bentayloruk
3个回答

6
你出现这个错误的原因是因为Bind通常是内核上的一个方法,所以你应该在模块外部执行它。此外,在解析Samurai之前,你应该先创建你的绑定,所以将最后两行交换一下位置:
static void Main(string[] args)
{
    IKernel kernel = new StandardKernel();
    kernel.Bind<IWeapon>().To<Sword>();
    kernel.Bind<Samurai>().ToSelf();
    var samurai = kernel.Get<Samurai>();

有时候不需要内核的原因是因为你可能在模块内看到了这样的教程。 NinjectModule 有一个受保护的 Bind 方法,可以执行相同的功能:

public class NinjaModule : NinjectModule {
    public void Load() {
       Bind<Samurai>().ToSelf()
       Bind<IWeapon>().To<Sword>();
    }
} 

当你的绑定变得有点复杂时,任何一种方法都是合适的,但建议将它们放入模块中。

编辑 确保你的所有类和接口都是公共的,否则Ninject无法执行它们。当未指定访问修饰符时,默认为internal。这解释了MethodAccessException


@Igor Zevaka 谢谢!但是在修改代码后,它会导致MethodAccessException。我已经更新了我的问题,您能否检查一下? - Gopi
更新的答案是,您需要绑定Samurai以及它的所有依赖项才能使此示例正常工作。 - Igor Zevaka
你能发布完整的异常文本和堆栈跟踪吗? - Igor Zevaka
将你的所有类和接口设为public - Igor Zevaka

1

Bind() 方法定义在 IBindingRoot 上。StandardKernelNinjectModule 都继承自实现了 IBindingRoot 接口的 BindingRoot

您可以在内核上绑定您的服务。

public static void Main()
{
    var kernel = new StandardKernel();
    kernel.Bind<IWeapon>().To<Sword>();
    // Optional, Ninject will try to resolve any non-registered concrete type.
    kernel.Bind<Samuari>().ToSelf();

    var samurai = kernel.Get<Samuari>();
}

或者通过使用 Ninject 模块

public class WeaponModule : NinjectModule
{
    public override void Load()
    {
        Bind<IWeapon>().To<Sword>();
        // Optional, Ninject will try to resolve any non-registered concrete type.
        Bind<Samuari>().ToSelf();
    }
}

然后加载模块

public static void Main()
{
    var module = new WeaponModule();
    var kernel = new StandardKernel(module);
    var weapon = kernel.Get<IWeapon>();
}

1
kernel.Bind<IWeapon>().To<Sword>();

或者在继承自NinjectModule的类中进行绑定。


+1 用于扩展 NinjectModule。他为什么不把它叫做 Ninjector 呢 ;-) - corlettk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接