简体   繁体   English

在WPF中以异步登录方式设置CurrentPrincipal

[英]Set CurrentPrincipal in an asynchronous login in WPF

I've been searching the web for this, and couldn't really find a solution that actually worked. 我一直在网上搜索此内容,但找不到真正有效的解决方案。 Situation is as follows: I've got a WPF application, where I want to present the user with a simple logon form. 情况如下:我有一个WPF应用程序,我想在其中向用户显示一个简单的登录表单。 Trying to work MVVM, so I've got a LoginViewModel with the following code behind the login command: 尝试使用MVVM,因此我在登录命令后有一个LoginViewModel,其中包含以下代码:

try
        {
            WithClient(servfact.GetServiceClient<IAccountService>(), proxy =>
            {
                principal = proxy.AuthenticateUser(Login, password);
            });
            Thread.CurrentPrincipal = principal;
        }
        catch(...) { ... }

"WithClient" is a short method in my viewmodel baseclass, which I use to instantiate and dispose of my service proxies: “ WithClient”是我的viewmodel基类中的一种简短方法,可用于实例化和处理我的服务代理:

    protected void WithClient<T>(T proxy, Action<T> codeToExecute)
    {
        try { codeToExecute(proxy); }
        finally
        {
            IDisposable toDispose = (proxy as IDisposable);
            if(toDispose != null) { toDispose.Dispose(); }
        }
    }

Now, most of my services are Async, and I've got an async variant of WithClient going on, which also works fine: 现在,我的大多数服务都是异步的,并且正在进行WithClient的异步变体,它也可以正常工作:

        protected async Task WithClientAsync<T>(T proxy, Func<T, Task> codeToExecute)
    {
        try { await codeToExecute(proxy); }
        finally
        {
            IDisposable toDispose = (proxy as IDisposable);
            if(toDispose != null) { toDispose.Dispose(); }
        }
    }

The trouble begins whenever I also want to do the login asynchronously. 每当我也想异步登录时,麻烦就开始了。 Obviously I don't want the UI to freeze up as I do the login (or visit any WCF service for that matter). 显然,我不希望UI在登录时冻结(或为此访问任何WCF服务)。 That in itself is working fine, but the problem sits in the piece of code where I set the CurrentPrincipal. 这样做本身可以很好地工作,但是问题出在我设置CurrentPrincipal的那段代码中。 This problem is probably familiar to most of you: it seems to set it just fine. 这个问题可能是大多数人都熟悉的:它似乎设置得很好。 Then in my program I want to use the CurrentPrincipal (either on the client side or to send the users login to a WCF service in a messageheader), but it seems to be reset to a standard GenericPrincipal. 然后,在我的程序中,我想使用CurrentPrincipal(在客户端或将用户登录名发送到消息头中的WCF服务),但似乎已重置为标准GenericPrincipal。 When I revert the login back to being synchronous, the CurrentPrincipal is just fine. 当我将登录恢复为同步状态时,CurrentPrincipal很好。 So in short: how do I set the principal in the asynchronous code, having it persist later on, instead of reverting back to a standard principal? 简而言之:如何在异步代码中设置主体,让它在以后继续存在,而不是恢复为标准主体?

Well, well, no answer in a year. 好吧,好吧,一年没有答案。 No worries, since I managed to solve this myself: I simply wrapped a singleton around it all: 不用担心,因为我设法自己解决了这个问题:我只是将所有内容包裹在一个单例中:

    public sealed class CurrentPrincipalFacade : IPrincipal
{
    #region Singleton mechanism

    private static readonly CurrentPrincipalFacade instance = new CurrentPrincipalFacade();
    public static CurrentPrincipalFacade Instance { get { return instance; } }
    private CurrentPrincipalFacade() { }

    #endregion

    #region IPrincipal members

    public IPrincipal Principal { get; set; }

    public IIdentity Identity { get { return Principal == null ? null : Principal.Identity; } }

    public bool IsInRole(string role) { return Principal != null && Principal.IsInRole(role); }

    public void Reset() { Principal = new GenericPrincipal(new GenericIdentity(""), new string[] { }); }
    #endregion}

So I set that after login. 因此,我在登录后进行了设置。 I guess the problem was I was setting the principal in another thread, which got lost when I got out of that? 我想问题是我在另一个线程中设置了主体,而当我退出该线程时却迷失了?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM