funq的servicestack - 按照惯例自动装配

Jor*_*ris 6 dependency-injection inversion-of-control convention-over-configur servicestack funq

我有一个服务,它在其构造函数中采用IMyDependency.IMyDependency,MyDependency和服务都存在于同一个程序集中.MyDependency有一个单一的,公共的无参数构造函数.

令我惊讶的是,这不起作用:

container.RegisterAutoWired<IMyDependency>();
Run Code Online (Sandbox Code Playgroud)

它抛出一个"System.NullReferenceException".

如果我这样做,它的工作原理:

container.RegisterAutoWiredAs<MyDependency, IMyDependency>();
Run Code Online (Sandbox Code Playgroud)

但那么,这样做:

container.RegisterAs<MyDependency, IMyDependency>();
Run Code Online (Sandbox Code Playgroud)

那么区别是什么呢?如果"自动布线"找不到具体的实现,并且对于是否可以解决需要依赖性的服务没有区别,那么什么是自动布线?

Funq应该能按惯例找到具体的实现吗?如果是这样的话,那个约定是什么,如果不是同名的话?

谢谢.

Ken*_*rdt 8

您的意思是"我如何实现搜索程序集的解决方案,并根据约定自动在ServiceStack IOC中注册类?"

如果是这样,我可能会为您提供解决方案:

  1. 创建一个可注入类将实现的接口.
  2. 让您的可注入类实现该接口.
  3. 在boot-strapping代码中,使用反射来搜索程序集并获取实现可注入接口的所有类的列表.
  4. 使用反射根据您的约定获取类名和接口.
  5. 调用ServiceStack IOC方法RegisterAutoWiredType并传入类和接口以注册它们.

例如,如果我们的命名约定是ClassName IClassName:

private static void RegisterCustomTypes(Container container)
{
  //Get the Assembly Where the injectable classes are located.
  var assembly = Assembly.GetAssembly(typeof(IInjectable));

  //Get the injectable classes 
  var types =assembly.GetTypes()
    .Where(m => m.IsClass && m.GetInterface("IInjectable") != null);

  //loop through the injectable classes
  foreach (var theType in types)
  {
    //set up the naming convention
    var className = theType.Name;
    var interfaceName = string.Concat("I", className);
    //create the interface based on the naming convention
    var theInterface = theType.GetInterface(interfaceName);
    //register the type with the convention
    container.RegisterAutoWiredType(theType, theInterface);
  }
}

public interface IInjectable
{

}

//This class can be injected
public interface ITestManager : IInjectable
{
    void Execute(int id);
}

public class TestManager : ITestManager
{
    public void Execute(int id)
    {
        throw new System.NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)


myt*_*thz 5

对于像这样的简单查询,最好只联系来源,例如,这里是RegisterAutoWired的源代码:

public IRegistration<T> RegisterAutoWired<T>()
{
    var serviceFactory = GenerateAutoWireFn<T>();
    return this.Register(serviceFactory);
}
Run Code Online (Sandbox Code Playgroud)

它通过Concrete implementation生成一个自动连接的工厂。接口没有实现,它需要是一个具体的类。

以及RegisterAs的源代码:

public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs 
{
    return this.RegisterAutoWiredAs<T, TAs>();
}
Run Code Online (Sandbox Code Playgroud)

这只是一个较短的别名,您可以使用它来代替 RegisterAutoWiredAs。

  • 它非常简单,它只会注入你注册的内容,如果你`Register&lt;MyDependency&gt;`,它会注入所有`MyDependency` 属性。如果您希望它注入`IMyDependency` 属性,那么您需要调用`RegisterAs&lt;MyDependency,IMyDependency&gt;`。 (3认同)
  • 在我的项目中,按照惯例,我有大约 200 个类:MyClass : IMyClass。所以根据这个每次我实现新类或删除可以为它接线吗?Unity、Windsor 和 StructureMap 按照惯例具有自动装配。 (2认同)