StructureMap and Nested Generics

寵の児 提交于 2019-12-11 01:48:28

问题


I am wondering if there is a way to wire up nested generics within StructureMap without having to specify the internal type or create type specific interfaces. I realize that this is a bit confusing, so a coding example might be a better explanation of the functionality that I am looking for.

public interface IParser<T> { }
public class Range<T> where T : struct { }
public class RangeParser<T> : IParser<Range<T>> { }

Theoretically, I would like to be able to follow StructureMap's open generic capabilities such as this:

For(typeof(IRepository<>)).Use(typeof(Repository<>)).

I realize that I cannot do this:

For(typeof(IParser<Range<>>).Use(typeof(RangeParser<>));

I have tried to do it via reflection's MakeGenericType, however, I seem to be running into issues with that approach.

var requestedType = typeof(IParser<>).MakeGenericType(typeof(Range<>));
For(requestedType).Use(typeof(RangeParser<>));

Any ideas would be greatly appreciated.


回答1:


StructureMap is quite limited when it comes to support for open generics. With Simple Injector on the other hand you can do the following:

// using SimpleInjector.Extensions;

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RangeParser<>));

This will map IParser<Range<T>> to RangeParser<T> where T is a struct. If you have multiple generic implementations for IParser<T> you can simply add extra implementations:

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RangeParser<>));
container.RegisterOpenGeneric(typeof(IParser<>), typeof(ReferenceTypeParser<>));

The only thing you need to make sure is that the registrations don't overlap. Simple Injector will throw an exception when you try to resolve (or inject) an closed IParser<T> type that can be handled by multiple registrations.

In case there is some overlap, you can supply a predicate to the RegisterOpenGeneric method like this:

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RestrictiveParser<>));
container.RegisterOpenGeneric(typeof(IParser<>), typeof(FallbackParser<>), 
    c => !c.Handled);

These registrations are evaluated in order of registration.

You can use generic type constraints as natural filters and Simple Injector will follow them. If generic type constraints don't cut it, you can always register partial open generic types:

container.RegisterOpenGeneric(typeof(IParser<>), 
    typeof(SomeParser<>).MakeGenericType(typeof(List<>));

From all IoC frameworks for .NET, Simple Injector has the best support for generic typing:

  • It understands generic type constraints.
  • It allows complex nested generic type mappings.
  • It allows supplying partial open generic types.
  • It allows applying generic decorators to types.
  • It allows conditionally applying generic decorators based on their generic type constraints.
  • It allows registering collections with that mix non-generic implementations and auto-determined closed versions of supplied open generic types.


来源:https://stackoverflow.com/questions/19010964/structuremap-and-nested-generics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!