在我的Angular应用程序中,我正在实现2项服务:
这两项服务相互依赖:
IdleService
中的方法)logout
调用AuthenticationService
方法来注销用户。这种方法导致了循环依赖问题。您是否知道如何避免它或如何通过更好的方法改变我的实际方法?
答案 0 :(得分:2)
在书Dependency Injection in .NET 2nd edition(§6.3)中,Mark Seemann和我描述了依赖周期通常是由Single Responsibility Principle违规造成的。我的印象是,在您的具体情况下也是如此。当一个类有很多不具有凝聚力的方法时,通常会违反SRP。
解决方案是将两个类public class TimeExtension : MarkupExtension, INotifyPropertyChanged
{
System.Threading.Timer _timer = null;
public TimeExtension() { }
public TimeExtension(TimeSpan interval)
{
Interval = interval;
}
public TimeSpan Interval { get; set; } = new TimeSpan(0, 0, 0, 0, 250);
#region CurrentTime Property
private DateTime _currentTime = default(DateTime);
public DateTime CurrentTime
{
get { return _currentTime; }
set
{
if (value != _currentTime)
{
_currentTime = value;
OnPropertyChanged();
}
}
}
#endregion CurrentTime Property
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] String propName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget provideValueTarget =
serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (provideValueTarget.TargetObject is DependencyObject targetobj)
{
if (provideValueTarget.TargetProperty is DependencyProperty targetProp)
{
System.Threading.TimerCallback tick
= new System.Threading.TimerCallback(o =>
{
try
{
CurrentTime = DateTime.Now;
}
catch (Exception ex)
{
_timer.Dispose();
_timer = null;
}
});
_timer = new System.Threading.Timer(tick, null, 0, (int)Interval.TotalMilliseconds);
}
}
// This is how it must be done in WPF
//return (new Binding("CurrentTime") { Source = this }).ProvideValue(serviceProvider);
// Xamarin
return new Binding("CurrentTime") { Source = this };
}
}
和AuthenticationService
中的任何一个(或者甚至两个)分成更小的类。
答案 1 :(得分:1)
我想说auth服务负责持有,管理和公开用户身份验证的状态。通过这个我说auth服务根本不应该关心用户空闲。这是空闲服务的责任。
所以我会在auth服务中创建一个BehaviorSubject来广播用户身份验证的状态。空闲服务可以使用主题来确定空闲计时器何时需要启动/停止。
export class AuthService {
user: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
logIn(){
// logic to log user in
this.user.next(true);
}
logOut(){
// logic to log user out
this.user.next(false);
}
}
现在,空闲服务可以注入auth服务并确定如何处理空闲计时器
export class IdleService {
constructor(private authService: AuthService){
this.authService.user.subscribe(res => {
// watch user authentication state and determine how to handle idle timer
});
}
idleOut(){
this.authService.logOut();
}
}
为了实现这一点,你必须在app加载时注入IdleService(例如在app.component中运行IdleService构造函数方法。我不确定这是否是最优雅的解决方案,但这是第一件事我想到了这一点。这是一个非常基本的stackblitz演示这个概念。
答案 2 :(得分:0)
您可以在IdleService
中创建一个观察者或主题,如果时间结束,则会返回断开连接消息。这样,只有AuthenticationService
导入IdleService
。例如:
import { IdleService } from './services/idle.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthenticationService {
disconnect: Obervable<boolean>;
constructor(private idleService: IdleService) {
this.disconnect = this.idleService.disconnectObservable;
this.disconnect.subscribe(res => {
if (res === true) {
this.logout();
}
});
}
logout() {
//some code here
}
}
在IdleService
:
import { Observable } from 'rxjs/Observable';
@Injectable()
export class IdleService {
public disconnectObservable: Observable<boolean>;
constructor() {
this.disconnectObservable = new Observable(observer => {
// insert your logic here
setTimeout(() => {
observer.next('true');
}, 1000);
setTimeout(() => {
observer.complete();
}, 3000);
});
}
}