servicetack с funq - автоматическая разводка по договоренности

У меня есть сервис, который принимает IMyDependency в своем конструкторе. IMyDependency, MyDependency и служба находятся в одной сборке. MyDependency имеет единственный открытый конструктор без параметров.

К моему удивлению, это не сработало:

container.RegisterAutoWired<IMyDependency>();

Выдает "System.NullReferenceException".

Это работает, если я делаю это:

container.RegisterAutoWiredAs<MyDependency, IMyDependency>();

Но тогда, это тоже так:

container.RegisterAs<MyDependency, IMyDependency>();

Так в чем же разница? Если "автоматическое подключение" не может найти конкретную реализацию, и не имеет значения, могут ли быть разрешены службы, требующие зависимости, то что такое "автоматическое подключение"?

Предполагается ли, что Funq сможет найти ваши конкретные реализации по соглашению? Если да, то что это за соглашение, если не одноименное?

Благодарю.

2 ответа

Решение

Для таких простых запросов лучше всего просто связаться с источником, например, вот исходный код для RegisterAutoWired:

public IRegistration<T> RegisterAutoWired<T>()
{
    var serviceFactory = GenerateAutoWireFn<T>();
    return this.Register(serviceFactory);
}

Он генерирует автоматическую фабрику над конкретной реализацией. Интерфейс не имеет реализации, он должен быть конкретным классом.

И исходный код для RegisterAs:

public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs 
{
    return this.RegisterAutoWiredAs<T, TAs>();
}

Это просто более короткий псевдоним, который вы можете использовать вместо RegisterAutoWiredAs.

Вы имеете в виду "как я могу реализовать решение для поиска по сборкам и автоматической регистрации классов в ServiceStack IOC на основе соглашения?"

Если так, у меня может быть решение для вас:

  1. Создайте интерфейс, который будут реализовывать ваши классы с возможностью внедрения.
  2. Ваши классы, способные к инъекции, реализуют этот интерфейс.
  3. В загрузочном коде используйте отражение для поиска в ваших сборках и получения списка всех классов, которые реализуют интерфейс, способный к внедрению.
  4. Используйте рефлексию, чтобы получить имя класса и интерфейс на основе ваших соглашений.
  5. Вызовите метод IOS ServiceStack 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();
    }
}