我在Web应用程序中使用OWIN + Microsoft.AspNet.Identity.Owin(v.2.0.0.0)。我按照广泛推荐的方式为每个Web请求注册UserManager / DbContext:
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
但两者都没有处理过。我瞥了一眼反射器,它似乎是扩展方法中的一个错误:
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app, Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback) where T: class, IDisposable
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (createCallback == null)
{
throw new ArgumentNullException("createCallback");
}
object[] args = new object[1];
IdentityFactoryOptions<T> options = new IdentityFactoryOptions<T> {
DataProtectionProvider = app.GetDataProtectionProvider()
};
IdentityFactoryProvider<T> provider = new IdentityFactoryProvider<T> {
OnCreate = createCallback
};
options.Provider = provider;
args[0] = options;
app.Use(typeof(IdentityFactoryMiddleware<T, IdentityFactoryOptions<T>>), args);
return app;
}
IdentityFactoryProvider有两个回调 - create和dispose,但是这里没有注册dispose回调。我也证实了我对记忆探测器的怀疑。
我没有在codeplex / github上看到Owin(实际上我认为它是开源的),所以我不知道在哪里问我的问题:还有其他人可以确认这是内存泄漏吗? 我不确定,因为谷歌没有说它,我希望它应该在任何地方讨论,如果这是一个错误。
答案 0 :(得分:6)
我也有他的问题,在CreatePerOwinContext中注册的任何内容都没有被处理掉。我正在使用v2.1。
这是一个临时修复,对我来说很有效,直到修复了这个lib。您基本上必须在以下类中手动注册使用Register与CreatePerOwnContext的每个类型,然后在启动过程结束时注册此自定义类:
public sealed class OwinContextDisposal : IDisposable
{
private readonly List<IDisposable> _disposables = new List<IDisposable>();
public OwinContextDisposal(IOwinContext owinContext)
{
if (HttpContext.Current == null) return;
//TODO: Add all owin context disposable types here
_disposables.Add(owinContext.Get<MyObject1>());
_disposables.Add(owinContext.Get<MyObject2>());
HttpContext.Current.DisposeOnPipelineCompleted(this);
}
public void Dispose()
{
foreach (var disposable in _disposables)
{
disposable.Dispose();
}
}
}
最后,您的启动过程会注册此课程:
app.CreatePerOwinContext<OwinContextDisposal>(
(o, c) => new OwinContextDisposal(c));
现在一切都将在请求管道的末尾正确处理。
答案 1 :(得分:5)
AppBuilderExtensions
类中的内存泄漏已在最新版本的Microsoft.AspNet.Identity.Owin
库(2.2.1)中修复。
我已经使用Reflector检查了代码,并在Dispose()
创建的对象的AppBuilderExtensions.CreatePerOwinContext()
方法中添加了断点。
答案 2 :(得分:1)
您可以将用CreatePeOwinContext()
创建的实例的逻辑放在用于创建此类内容的同一回调中。
那就是:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext<ClassIWantOneInstancePerContext>(ClassIWantOneInstancePerContext.Create);
//other code...
}
}
然后你应该只关心在用于实例化你的类的回调中包含对DisposeOnPipelineCompleted()
的调用。那就是:
public class ClassIWantOneInstancePerContext
{
//other code...
public static ClassIWantOneInstancePerContext Create()
{
ClassIWantOneInstancePerContext TheInstance = new ClassIWantOneInstancePerContext();
HttpContext.Current.DisposeOnPipelineCompleted(TheInstance);
return TheInstance;
}
}
另外,不要忘记在课程定义中加入Dispose()
方法!
答案 3 :(得分:0)
用法:app.CreatePerRequest<AuthorizationContext>();
扩展方法:
public static IAppBuilder CreatePerRequest<T>(this IAppBuilder builder )where T:IDisposable
{
builder.Use(async (context, next) =>
{
var resolver = context.Get<IDependencyScope>();
using (var instance = (T) resolver.GetService(typeof (T)))
{
context.Set<T>(instance);
if (next != null)
{
await next();
}
}
});
return builder;
}
要使用依赖注入,您必须配置owin:app.UseScopePerOwinRequest(_dependencyResolver);
- 这应该是第一个中间件..
public static IAppBuilder UseScopePerOwinRequest(this IAppBuilder builder,IDependencyResolver resolver)
{
builder.Use(async (context, next) =>
{
using (var instance = resolver.BeginScope())
{
context.Set<IDependencyScope>(instance);
if (next != null)
{
await next();
}
}
});
return builder;
}
要使上述代码工作,您必须使用任何容器实现IDepedencyResolver。