C# 在WPF中的异步登录中设置CurrentPrincipal

C# 在WPF中的异步登录中设置CurrentPrincipal,c#,.net,wpf,wcf,asynchronous,C#,.net,Wpf,Wcf,Asynchronous,我一直在网上搜索这个问题,但找不到真正有效的解决方案。情况如下:我有一个WPF应用程序,我想向用户展示一个简单的登录表单。正在尝试使用MVVM,因此我有一个LoginViewModel,在login命令后面有以下代码: try { WithClient(servfact.GetServiceClient<IAccountService>(), proxy => { principal

我一直在网上搜索这个问题,但找不到真正有效的解决方案。情况如下:我有一个WPF应用程序,我想向用户展示一个简单的登录表单。正在尝试使用MVVM,因此我有一个LoginViewModel,在login命令后面有以下代码:

try
        {
            WithClient(servfact.GetServiceClient<IAccountService>(), proxy =>
            {
                principal = proxy.AuthenticateUser(Login, password);
            });
            Thread.CurrentPrincipal = principal;
        }
        catch(...) { ... }
试试看
{
WithClient(servfact.GetServiceClient(),代理=>
{
主体=proxy.AuthenticateUser(登录名、密码);
});
Thread.CurrentPrincipal=主体;
}
捕获(…){…}
“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(); }
        }
    }
客户端受保护的void(T代理,操作代码执行)
{
尝试{codeToExecute(proxy);}
最后
{
IDisposable toDispose=(代理为IDisposable);
如果(toDispose!=null){toDispose.Dispose();}
}
}
现在,我的大多数服务都是异步的,而且我有一个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(); }
        }
    }
使用ClientAsync(T代理,Func codeToExecute)保护异步任务
{
尝试{等待代码执行(代理);}
最后
{
IDisposable toDispose=(代理为IDisposable);
如果(toDispose!=null){toDispose.Dispose();}
}
}

每当我还想异步登录时,问题就开始了。显然,我不希望UI在登录时冻结(或访问任何WCF服务)。这本身工作正常,但问题在于我设置CurrentPrincipal的代码段。这个问题对你们大多数人来说可能都很熟悉:它似乎设置得很好。然后,在我的程序中,我想使用CurrentPrincipal(在客户端或在messageheader中将用户登录发送到WCF服务),但它似乎被重置为标准的GenericPrincipal。当我将登录恢复为同步登录时,CurrentPrincipal很好。简而言之:我如何在异步代码中设置主体,使其在以后持久化,而不是恢复到标准主体

好吧,好吧,一年内没有答案。不用担心,因为我自己解决了这个问题:我只是简单地用一个单件包起来:

    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}

所以我在登录后设置。我想问题是我在另一个线程中设置了主体,当我离开线程时,它丢失了?

我忍不住想知道,你的
with client
和语句之间有什么区别?好吧,如果我对using语句做了同样的事情,我需要让我的服务工厂创建必要的服务,执行我要执行的wcf调用,然后再次处置服务。我每次都必须手动操作。现在,我只需要将我想用“withclient”进行的调用打包,而不必担心关闭代理。我在代码中进行错误处理(codeToExecute),不管那里发生了什么,我确信finally块(我处理代理的地方)将始终被执行。但这正是
使用
所做的。如果您使用JustDecompile进行分解,您将看到使用
变成了
try
最后执行dispose的块,以防对象当时不为null。使用
是公正的。在这种情况下,我相信你刚刚教了我一些东西;)非常感谢。关于实际问题:查看这个url,我在那里发布了相同的问题,以及我自己的解决方案。关于在using块中包装WCF调用的快速更新:当代理最终处于故障状态时,dispose调用会向您抛出异常。正确的方法是避免使用块,并在处理代理之前测试代理的状态使用客户端(T proxy,Action codeToExecute)保护void{try{codeToExecute(proxy);}最后{var client=proxy作为ICommunicationObject;client.disposeSafley();}`