gpt4 book ai didi

c# - Autofac:使用类型参数条件解析开放式泛型

转载 作者:行者123 更新时间:2023-11-30 20:41:21 27 4
gpt4 key购买 nike

在使用 Autofac 的应用程序中作为它的 IoC 容器,我有一个带有两个类型参数的通用接口(interface):

public interface IMapper<TSource, TTarget>
{
TTarget GetTarget(TSource source);
}

和一个包装接口(interface)来动态选择适当的IMapper<TSource, TTarget>取决于其输入参数类型:

public interface IDynamicMapper
{
T GetTarget<T>(object source);
}

我希望我的 IDynamicMapper 实现在运行时找到合适的 IMapper<TSource, TTarget>组件,使用 Autofac,它有一个 TSource等于source.GetType()TTarget作为 T 的派生类型(或 T 本身):

public class DynamicMapper : IDynamicMapper
{
private readonly ILifetimeScope _scope;

public DynamicMapper(ILifetimeScope scope)
{
this._scope = scope;
}

T IDynamicMapper.GetTarget<T>(object source)
{
Type sourceType = source.GetType();
Type targetBaseType = typeof(T);

//TODO: find an IMapper<TSource, TTarget> implementation where
// 1) Condition on TSource: typeof(TSource) == sourceType
// 2) Condition on TTarget: targetBaseType.IsAssignableFrom(typeof(TTarget))
// Many implementations can potentially match these criterias,
// choose the 1st one
// (this should not happen if the application is designed correctly)

if (mapper == null)
{
throw new ArgumentException(
"Could not find an IMapper<TSource, TTarget> implementation" +
" for the supplied parameters"
);
}

// call mapper.GetTarget(source) and return the result
// (mapper is probably dynamic, but its runtime type implements
// TTarget IMapper<TSource, TTarget>.GetTarget(TSource source))
}
}

我的所有组件都注册到 Autofac 容器作为它们在应用程序另一部分的服务接口(interface)(使用程序集扫描记录)。


更新 1

根据 Steven 的相关回答,我更新了我的界面以使用方差:

public interface IMapper<in TSource, out TTarget>
{
TTarget GetTarget(TSource source);
}

我的动态映射器的 GetTarget()方法如下所示:

T IDynamicMapper.GetTarget<T>(object source)
{
Type sourceType = source.GetType();
Type targetBaseType = typeof(TTarget);
Type mapperType = typeof(IMapper<,>).MakeGenericType(sourceType, targetBaseType);

// This fails with ComponentNotRegisteredException
dynamic mapper = this._scope.Resolve(mapperType);

// This also fails (mapper is null):
// IEnumerable<object> mappers = (IEnumerable<object>)this._scope.Resolve(typeof(IEnumerable<>).MakeGenericType(mapperType));
// dynamic mapper = mappers.FirstOrDefault();

// Invoke method
return mapper.GetTarget((dynamic)source);
}

但是,当调用 Resolve(mapperType) 时或 Resolve(typeof(IEnumerable<>).MakeGenericType(mapperType)) ,组件未解析,尽管它存在于容器的注册中,映射到服务 IMapper<TSource, TTarget> .第一次调用抛出异常,第二次调用返回一个空的可枚举对象。

最佳答案

这应该可以解决问题:

T IDynamicMapper.GetTarget<T>(object source) {

Type mapperType = typeof(IMapper<,>).MakeGenericType(source.GetType(), typeof(T));

// Will throw when no registration exists.
// Note the use of 'dynamic'.
dynamic mapper = scope.Resolve(mapperType);

return (T)mapper.GetTarget<T>((dynamic)source);
}

关于c# - Autofac:使用类型参数条件解析开放式泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32497341/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com