在StructureMap中自动解析Interface <T>到Implementation <T>(仅与泛型类型T不同)

Mic*_*ins 22 c# structuremap asp.net generics

我有一个接口(IRepository<T>),目前正在为每个特定的存储库进行扩展,即:IUserRepository : IRepository<User>.

这些接口中的每一个都具有相应的具体类,即:UserRepository : Repository<User>, IUserRepository.

这些单独的存储库不添加任何其他功能,它们都是空接口/类,仅用于传递泛型.

我用StructureMap解决IUserRepositoryUserRepository使用注册表与组装扫描仪和一些命名约定.

我希望这可以转向一种更优化的状态,而不是传递实例IUserRepository并将其解析UserRepository,我可以传递IRepository<User>并解决它Repository<User>.

这将消除创建这些额外的空接口和类的需要.

我无法找到一种方法来使用StructureMap的配置来设置这种通用映射.像这样的东西:

For(typeof(IRepository<>).Use(typeof(Repository<>)).WithTheGenericTypeFromTheInterfaceSuppliedAsATypeParameter();
Run Code Online (Sandbox Code Playgroud)

编辑

得到前几个答案之后,我想再澄清一下这个问题.

我不想为For配置的位创建单独的类.我希望在我的代码中有以下类/接口:

  • IRepository<T> where T : Entity
  • Repository<T> : IRepository<T> where T : Entity
  • Person : Entity
  • Product : Entity
  • Order : Entity
  • Whatever : Entity

并按照惯例实现以下映射:

IRepository<Person> => Repository<Person>
IRepository<Product> => Repository<Product>
IRepository<Order> => Repository<Order>
IRepository<Whatever> => Repository<Whatever>
Run Code Online (Sandbox Code Playgroud)

但我不想为每个人创建一个映射,ala:

For<IRepository<Person>>().Use<Repository<Person>>();
For<IRepository<Product>>().Use<Repository<Product>>();
For<IRepository<Order>>().Use<Repository<Order>>();
For<IRepository<Whatever>>().Use<Repository<Whatever>>();
Run Code Online (Sandbox Code Playgroud)

我想要一个适用于任何IRepository的映射:

For<IRepository<>>().Use<Repository<>>().WithTheSameGenericType();
Run Code Online (Sandbox Code Playgroud)

然后我会使用它将存储库注入服务:

public MyService(IRepository<User> userRepository)
Run Code Online (Sandbox Code Playgroud)

并期望Repository<User>在运行时解决.

Mic*_*ins 25

原来没有花哨的方法来调用,或者没有花哨的布线,你只需使用ForUse(非通用版本):

public class DataRegistry : Registry
{
    public DataRegistry()
    {
        For(typeof (IRepository<>)).Use(typeof(Repository<>));
    }
}
Run Code Online (Sandbox Code Playgroud)

当我注入IRepository<Person>它时,它正在被解决为Repository<Person>现在.

我遇到错误104,说Repository不能插入IRepository.这是因为存储库已被标记abstract.使它成为非抽象的,修复了错误并且它正在按预期工作.


tyr*_*ron 6

我建议你看看这个AddAllTypesOf方法.我有一些类似的代码,并通过使用它来实现我的目标(并保持自动注册功能工作).

在你的情况下,你应该改变

For<IRepository<Person>>().Use<Repository<Person>>();
For<IRepository<Product>>().Use<Repository<Product>>();
For<IRepository<Order>>().Use<Repository<Order>>();
For<IRepository<Whatever>>().Use<Repository<Whatever>>();
Run Code Online (Sandbox Code Playgroud)

AddAllTypesOf(typeof(IRepository<>));
Run Code Online (Sandbox Code Playgroud)

最后,您的容器将类似于:

return new Container(x =>
        {
            x.Scan(y =>
            {
                y.TheCallingAssembly();
                y.AddAllTypesOf(typeof(IRepository<>));
                y.WithDefaultConventions();
            });
        });
Run Code Online (Sandbox Code Playgroud)