我的代码将动态扫描程序集以实现AutoMapper Profile类的实现,并构建一个映射器以与Unity DI一起使用。最近,我发现需要使用IValueResolver接口。此类需要在其中注入资源依赖项,以便在模型之间执行转换。
我可以在automapper配置中添加一行,强制它使用unity来解析IValueResolvers。
cfg.ConstructServicesUsing(type => container.Resolve(type));
我无法确定如何动态地为Unity注册通用接口的多个实例。
我可以硬编码
container.RegisterType<IValueResolver<Class1, Class2, string>,Class1ToClass2ValueResolver>();
但是,我宁愿动态扫描和注册它们。
答案 0 :(得分:1)
可能有更好的方法,这种方法可能有点天真,可能无法处理所有嵌套类型层次结构或同一通用接口的多个实现,但这种方法适用于已发布的案例。也许可以通过使用一些注册公约功能来清理它。
var resolverTypes = .AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic) // Exclude dynamic assemblies
.Select(a => a.GetTypes())
.SelectMany(t => t) // flatten Types for each assembly into one
.Select(t => t.GetTypeInfo())
.Where(t =>
t.ImplementedInterfaces.Any(i =>
i.IsGenericType && i.GetGenericTypeDefinition()
.IsAssignableFrom(typeof(IValueResolver<,,>))))
.Select(t => new
{
Inteface = t.ImplementedInterfaces.First(i =>
i.IsGenericType && i.GetGenericTypeDefinition()
.IsAssignableFrom(typeof(IValueResolver<,,>))),
Type = t
});
var container = new UnityContainer();
foreach (var resolverType in resolverTypes)
{
container.RegisterType(resolverType.Inteface, resolverType.Type);
var resolver = container.Resolve(typeof(IValueResolver<Class1, Class2, string>));
Debug.Assert(resolver.GetType() == typeof(Class1ToClass2ValueResolver));
}
努力工作是获得正确的类型:
首先获取所有程序集,排除动态程序集,并展平为可枚举的类型(而不是Enumerable<Type[]>
)。接下来只选择具有通用接口的类并匹配开放的通用IValueResolver<,,>
接口,并返回具有匹配的封闭通用接口的类型。
一旦我们掌握了这些信息,只需注册从接口到实现的映射即可。在这种情况下,IValueResolver<ClassA, ClassB, string>
到Class1ToClass2ValueResolver
。以下是使用的示例类和接口:
public class Class1 { }
public class Class2 { }
public interface IValueResolver<U, V, W> { }
public class Class1ToClass2ValueResolver : IValueResolver<Class1, Class2, string> { }