如何使用Ninject约定扩展而不引用Assembly(或其中的类型) [英] How to use Ninject Conventions extension without referencing Assembly (or Types within it)

查看:96
本文介绍了如何使用Ninject约定扩展而不引用Assembly(或其中的类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



一般问题:



我有一个ASP.Net MVC2应用程序与以下项目:MyApp.Web,MyApp.Services,MyApp.Data。



我们的代码接口并使用Ninject 2进行DI / IoC。



然而,我正在得到厌倦了打字(并忘记输入):

 绑定< ISomeService> .To< SomeService> 

所以,了解Ninject.Extensions.Convensions,我试图用它来自动扫描和注册模块和类型为IXxxx => Xxxx的简单依赖项。



我尝试的是(但不够):



我可以使用以下代码设置Ninject,并且一切似乎都按预期的方式进行连接。

  public static IKernel Initialize()
{
var kernel = new StandardKernel();

kernel.Scan(a => {
a.FromAssemblyContaining< MyApp.Data.SomeDataClass>();
a.FromAssemblyContaining< MyApp.Services.SomeServiceClass>() ;
a.AutoLoadModules();
a.BindWithDefaultConventions();
a.InTransientScope();
});

返回内核;
}



我想要完成什么:



但是,我想采取一些这样的方式,我认为被支持,但我似乎无法让它工作。



由于我们的MyApp.Web项目根本没有使用(直接)从MyApp.Data,我试图避免引用MyApp.Data。使用上述代码,由于对SomeDataClass的编译时间引用,因此我必须从MyApp.Web引用MyApp.Data。



我希望指定Ninject的程序集的名称进行扫描和注册。似乎公约扩展通过从重载中支持这一功能,该方法采用字符串(或枚举字符串)。



我尝试了什么以及如何中断:



所以,我已经尝试了几个变体在From重载:

  public static IKernel Initialize()
{
var kernel = new StandardKernel();

kernel.Scan(a => {
a.From(MyApp.Data);
a.From(MyApp.Services.dll);
a.From(AnotherDependency,Version = 1.0.0.0,PublicKeyToken = null); // etc。等等与From(...)的
a.AutoLoadModules();
a.BindWithDefaultConventions();
a.InTransientScope();
});

返回内核;
}

但是我收到FileNotFoundExceptions的消息,如:


无法加载文件或程序集
'file:/// C:\Program Files
(x86)\Common Files\ Microsoft
Shared\DevServer\10.0\MyApp.Data'
或其依赖关系之一。系统
找不到指定的文件
:file:/// C:\Program文件
(x86)\Common Files\Microsoft
Shared\\ \\ DevServer\10.0\




我发现自己试图解决这个问题:



我已经查看了Ninject.Extensions.Conventions的源代码,我承认我完全失去了应该如何工作,但我可以看到它在做什么。 >

组装扫描器建立一个要扫描的程序集列表,我们称之为各种FromXXX方法。



当我调用From (assemblyName)方法,它首先检查列表是否已经包含任何程序集,其中assembly.AssemblyName.Name等于我传入的名称(而AssemblyName.Name是简单名称,即MyApp。数据,根据MSDN)。



流程通过一些不重要的方法,在FindAssemblies方法中登陆。该方法采用我传递的名称(我们已经看到这个名称应该是一个简单的程序集名称)。然后,它将创建一个新的AssemblyName,我们传入的名称用作AssemblyName.CodeBase。



然后,它尝试将程序集加载到临时AppDomain中。这是以上例外的失败步骤。



显然,搜索的路径是错误的,但是我不能通过From()方法提供路径。这也不行。



我尝试过一些其他的FromXXX方法,但是我已经无所适从,已经花了太多时间。 FromAssembliesInPath和FromAssembliesMatching也不起作用,因为它再次在完全错误的目录中搜索。



呃再次出现什么问题:



任何人都可以解释如何让Ninject约定以名称加载程序集,而不需要通过指定包含的类型来创建对程序集的引用并加载它们。请。



我已经通过页面和页面搜索了 Ninject google group ,我已经阅读了 only (所以似乎)相关文档,并且无法解决它..但是。

解决方案

这个问题在邮件列表中回答。 http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64



简而言之:


  1. 表单(路径)需要一个路径相对于工作目录或绝对路径

  2. 当加载到加载上下文中时,程序集必须位于探测路径中,以避免在切换加载上下文时出现其他问题。

  3. 开发服务器使所有程序集都复制到自己的目录中,这使得无法使用调用程序集创建路径。这意味着使用开发服务器的网络应用程序的唯一方法。

  4. 我们将在以后的版本中添加对组件的完整限定名称的支持,以使其更容易。


Sorry in advance for the long question, it's long because I've been digging at this all day.

The general problem:

I have an ASP.Net MVC2 application with the following projects: MyApp.Web, MyApp.Services, MyApp.Data.

We code to interfaces and utilize Ninject 2 for DI/IoC.

However, I'm getting awfully tired of typing (and forgetting to type):

Bind<ISomeService>.To<SomeService>;

So, knowing about Ninject.Extensions.Convensions, I have attempted to use it to automatically scan and register modules and simple dependencies of the type IXxxx => Xxxx.

What I tried that works (but isn't quite enough):

I can use the following code to setup Ninject, and everything seems to get wired up as expected.

    public static IKernel Initialize()
    {
        var kernel = new StandardKernel();

        kernel.Scan(a => {
                        a.FromAssemblyContaining<MyApp.Data.SomeDataClass>();
                        a.FromAssemblyContaining<MyApp.Services.SomeServiceClass>();
                        a.AutoLoadModules();
                        a.BindWithDefaultConventions();
                        a.InTransientScope();
                    });

        return kernel;
    }

What I want to accomplish instead:

However ... I'd like to take this a bit further in a way I think is supported, but I cannot seem to get it working.

Since our MyApp.Web project uses nothing at all (directly) from MyApp.Data, I am trying to avoid a reference to MyApp.Data. With the above code, I must reference MyApp.Data from MyApp.Web because of the compile time reference to SomeDataClass.

I would prefer to specify the name of an assembly for Ninject to scan and register. It seems the Conventions extension supports this through the From overloads that take a string (or enumerable of strings).

What I tried and how it breaks:

So, I've tried several variations on the From overloads:

    public static IKernel Initialize()
    {
        var kernel = new StandardKernel();

        kernel.Scan(a => {
                        a.From("MyApp.Data");
                        a.From("MyApp.Services.dll");
                        a.From("AnotherDependency, Version=1.0.0.0, PublicKeyToken=null"); //etc., etc. with the From(...)'s
                        a.AutoLoadModules();
                        a.BindWithDefaultConventions();
                        a.InTransientScope();
                    });

        return kernel;
    }

But I receive FileNotFoundExceptions with a message like:

Could not load file or assembly 'file:///C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\MyApp.Data' or one of its dependencies. The system cannot find the file specified.":"file:///C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\

What I've found trying to solve this myself:

I've checked out the source for Ninject.Extensions.Conventions, and I'll admit I get totally lost as to how this is supposed to work, but I can see what it is doing.

The assembly scanner builds up a list of assemblies to scan as we call various FromXXX methods.

When I call the From("assemblyName") method, it first checks if the list already contains any assemblies where the assembly.AssemblyName.Name equals the name I passed in (and AssemblyName.Name is the simple name, i.e. MyApp.Data, according to MSDN).

Flow passes through a couple unimportant methods, landing in the FindAssemblies method. This method takes the name I passed in (which we already saw is supposed to be a simple assembly name). It then creates a new AssemblyName, with our passed in name used as the AssemblyName.CodeBase.

Then, it attempts to Load the assembly into a temporary AppDomain. This is the step that fails with the above exception.

Obviously, the path it's searching is wrong, but I cannot supply a path through the From() method. That doesn't work either.

I've tried some of the other FromXXX methods, but I've gotten nowhere and spent too much time on this already. The FromAssembliesInPath and FromAssembliesMatching also do not work because, again, it is searching in the completely wrong directory.

Uh .. what was the question again:

Can anyone explain how to get Ninject Conventions to load assemblies by name, without creating a reference to the assembly and loading it by specifying a contained type? Please.

I've already searched through pages and pages of the Ninject google group, and I've read it's only (so it seems) relevant documentation and have not been able to solve it .. yet.

解决方案

This question was answerd on the mailing list. http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64

In Short:

  1. Form(path) takes a path either relative from the working directory or absolute
  2. The assembly must reside in a probing path as it is loaded into the load context to avoid other problems with switching the loading context.
  3. The development server makes all complicated as it copies all assemblies into their own directory, which makes it impossible to use the calling assembly to create the path. This means the only way for web apps using the development server.
  4. We will add support for full qualified names of assemblies in a future version to make this easier.

这篇关于如何使用Ninject约定扩展而不引用Assembly(或其中的类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆