Как использовать соглашение для IRepository <T>с отображением StructureMap - PullRequest
5 голосов
/ 30 июня 2011

Есть ли способ в StructureMap сделать такое повторяющееся отображение одной строкой или соглашением?

    For<IRepository<Mailout>>().Use<MailoutRepository>();
    For<IRepository<MailServer>>().Use<MailServerRepository>();
    For<IRepository<MailoutStatus>>().Use<MailoutStatusRepository>();
    For<IRepository<MailoutTemplate>>().Use<MailoutTemplateRepository>();
    For<IRepository<Publication>>().Use<PublicationRepository>();
    For<IRepository<Recipient>>().Use<RecipientRepository>();

Ответы [ 4 ]

5 голосов
/ 01 июля 2011

Чтобы отобразить IRepository<Mailout> на MailoutRepository, используйте:

var c = new Container(x =>
{
    x.Scan(scan =>
    {
        // there are other options to expand which assemblies to scan for types
        scan.TheCallingAssembly(); 
        scan.ConnectImplementationsToTypesClosing(typeof (IRepository<>));
    });
});

Чтобы отобразить IRepository<Mailout> на Repository<Mailout>, используйте:

var c = new Container(x =>
{
    x.For(typeof (IRepository<>)).Use(typeof (Repository<>));
});
0 голосов
/ 01 июля 2011
Scan(x =>
{
    x.WithDefaultConventions();
    x.AssemblyContainingType(typeof(UserRepository));
    x.AddAllTypesOf(typeof(Repository<>));
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});

WithDefaultConventions - важная часть показанного кода, потому что с этим параметром вы говорите StructureMap, чтобы использовать соглашение о сопоставлении IUserRepository с UserRepository. Поэтому StructureMap исходит из предположения, что класс назван как имя интерфейса без префикса I.

0 голосов
/ 30 июня 2011

Вот обходной путь, так как мы не могли найти более короткий способ сделать это отображение.

Во-первых, сопоставьте с открытым универсальным классом реализации, как обсуждалось в другом месте :

For(typeof(IRepository<>)).Use(typeof(ConcreteRepository<>));

Затем для каждого репозитория с пользовательским поведением добавьте методы расширения в соответствующий интерфейс. Например, предположим, что у вашего MailoutStatusRepository есть метод GetStatus(), вы можете перевести его в метод расширения на IRepository<MailoutStatusRepository>:

public static Status GetStatus(this IRepository<MailoutStatusRepository> repo,
                               Mailout mail)
{
    return mail.Status;  // or whatever
}

Теперь у вас есть настраиваемое поведение репозитория, и вам не нужно беспокоиться о преобразовании вывода StructureMap в какой-то пользовательский класс:

var repo = container.GetInstance<IRepository<MailoutStatusRepository>>();
var status = repo.GetStatus(mailout);

Еще одно преимущество этого подхода заключается в том, что ваше пользовательское поведение репозитория работает независимо от реализации вашего репозитория: в тестах и ​​в рабочем коде. Единственный недостаток (я думаю) заключается в том, что ваши репозитории обязательно не содержат состояний, но мы вообще не обнаружили в этом проблемы.

0 голосов
/ 30 июня 2011

Вы можете создать что-то вроде базы репозитория:

public class RepositoryBase<T> : IRepository<T> where T : Entity

, а затем получить что-то вроде этого:

public class UserRepository : RepositoryBase<User>, IUserRepository
public class OtherRepository : RepositoryBase<Other>, IOtherRepository

, где ваши интерфейсы репозиториев реализуют общий интерфейс репозитория, такой как:

public interface IUserRepository : IRepository<User>
public interface IOtherRepository : IRepository<Other>

и тогда вы можете зарегистрировать это так:

For(typeof (IRepository<>)).Use(typeof (RepositoryBase<>));

Это работает для меня.

...