c# - ServiceStack IContainerAdapter适配Autofac 5.2.0版本
问题描述
我正在尝试将最新的Autofac包升级到5.2.0
,但由于界面更改,并没有真正成功,
从 ( Autofac 4.9.4
)
public static class ResolutionExtensions
{
public static bool TryResolve<T>(this IComponentContext context, out T instance);
}
至 ( Autofac 5.2.0
)
public static class ResolutionExtensions
{
public static bool TryResolve<T>(this IComponentContext context, out T instance)
where T : class;
}
ServiceStack包有一个IContainerAdapter接口 ( ServiceStack.Interfaces 5.8.0
)
public interface IResolver
{
T TryResolve<T>();
}
public interface IContainerAdapter : IResolver
{
T Resolve<T>();
}
我的AutofacIocAdapter实现了这个IContainerAdapter
public class AutofacIocAdapter : IContainerAdapter
{
public T TryResolve<T>()
{
if (m_Container.TryResolve<Autofac.ILifetimeScope>(out var scope) &&
scope.TryResolve<T>(out var scopeComponent))
{
return scopeComponent;
}
if (m_Container.TryResolve<T>(out var component))
{
return component;
}
return default(T);
}
}
但升级Autofac后出现编译错误
Error CS0452 The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'ResolutionExtensions.TryResolve<T>(IComponentContext, out T?)'
有什么建议可以解决吗?
解决方案
如果没有来自 C# 的约束,您将无法从方法调用具有类约束的类,但您可以使用反射来调用它。
但是您的第一次尝试应该是绕过带有约束的 API。查看AutoFac 的 TryResolve 实现将显示它们在内部调用的 API:
public static bool TryResolve<T>(this IComponentContext context, out T? instance)
where T : class
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
object? component;
// Null annotation attributes only work if placed directly in an if statement.
if (context.TryResolve(typeof(T), out component))
{
instance = (T)component;
return true;
}
else
{
instance = default;
return false;
}
}
因此,您只需要使用约束绕过他们的通用 API 并调用他们调用的相同运行时类型 API,例如:
public class AutofacIocAdapter : IContainerAdapter
{
private readonly Autofac.IContainer container;
public AutofacIocAdapter(Autofac.IContainer container) =>
this.container = container;
public T TryResolve<T>()
{
if (container.TryResolve<Autofac.ILifetimeScope>(out var scope) &&
scope.TryResolve(typeof(T), out var scopeComponent))
return (T)scopeComponent;
if (container.TryResolve(typeof(T), out var component))
return (T)component;
return default;
}
public T Resolve<T>()
{
var ret = TryResolve<T>();
return !ret.Equals(default)
? ret
: throw new Exception($"Error trying to resolve '{typeof(T).Name}'");
}
}
推荐阅读
- ios - 如何使用 MethodChannels 将 Siri 集成到 Flutter 中?
- arrays - 如何使用 ngFor angular 迭代对象内的数组内容
- linux - 从 cron 作业运行时,Bash 脚本会产生不同的输出
- javascript - 基于值和数组过滤对象作为值js
- maven - 使用 Dockerfile 混合 Docker 图像
- javascript - 单击 HTML 按钮时未调用 JavaScript 函数
- php - 如何获取日期之间的行并将他们的子行放在另一个表中 - Laravel Eloquent
- c++ - C++:使用派生类指针(指向派生类对象)调用继承的虚方法导致编译错误
- javascript - ListView 仅在上下滚动时刷新
- java - LTV 在 PDF 中启用签名