StructureMap OnCreation с универсальными типами - PullRequest
3 голосов
/ 26 октября 2011

Привет, я хотел бы вызвать метод Foo после того, как StructureMap создаст экземпляр репозитория, поэтому есть метод для этого, называемый OnCreation.

x.For(typeof(IRepository<>))
 .Use(typeof(Repository<>))
 .OnCreation((ctx, instance) => { instance.Foo() });

Но компилятор, конечно, не может определить тип, поэтомуЯ попытался указать универсальный тип следующим образом:

x.For(typeof(IRepository<>))
 .Use(typeof(Repository<>))
 .OnCreation<Repository<>>((ctx, instance) => { instance.Foo() });

Это не скомпилируется, даже не будет проанализировано (недопустимый термин выражения '>).Я пытался создать объект Action самостоятельно, но безуспешно.Затем я узнал об InstanceInterceptor, поэтому я написал класс, но не могу понять, как его подключить. Должен быть метод InterceptWith, но он недоступен для ConfiguredInstance, который является типом результата не универсального метода Use.

Я знаю, что могу взломать это многими другими способами, но я хотел бы сделать это в рамках отображения StructureMap.

Пожалуйста, помогите:)

1 Ответ

2 голосов
/ 06 ноября 2011

Если ваш метод Foo() не требует доступа к универсальному типу, вы можете абстрагировать его в другой интерфейс:

public interface IRepository
{
    void Foo();
}

public interface IRepository<T> : IRepository
{
}

public class Repository<T> : IRepository<T>
{
    public void Foo()
    {

    }
}

Затем настроить StructureMap:

cfg.For(typeof(IRepository<>)).Use(typeof(Repository<>))
    .OnCreation<IRepository>((ctx, handler) =>
{
    handler.Foo();
});

С открытыми универсальными типами дела обстоят невероятно сложно, и я часто обнаруживаю, что проще передать дополнительную логику инициализации на завод.Вместо внедрения IRepository<T>, введите IRepositoryFactory<T>, который может выполнить любую дополнительную инициализацию, которая вам нужна (вы все равно можете добавить IRepository<T> в свою фабрику, если вам не нравится статическая ссылка StructureMap):

public interface IRepositoryFactory<T>
{
    IRepository<T> Create();
}

public class RepositoryFactory<T> : IRepositoryFactory<T>
{
    public IRepository<T> Create()
    {
        var repo = ObjectFactory.GetInstance<IRepository<T>>();
        repo.Foo();

        return repo;
    }
}
...