标签: unsubscribe

使用IDisposable取消订阅事件

我有一个类来处理来自WinForms控件的事件.根据用户正在做的事情,我正在引用该类的一个实例并创建一个新实例来处理同一事件.我需要先从事件中取消订阅旧实例 - 这很容易.如果可能的话,我想以非专有方式这样做,看起来这是IDisposable的工作.但是,大多数文档仅在使用非托管资源时才建议使用IDisposable,这在此处不适用.

如果我实现IDisposable并取消订阅Dispose()中的事件,我是否会歪曲它的意图?我应该提供一个Unsubscribe()函数并调用它吗?


编辑:这是一些虚拟代码,它显示了我正在做的事情(使用IDisposable).我的实际实现与一些专有数据绑定(长篇故事)有关.

class EventListener : IDisposable
{
    private TextBox m_textBox;

    public EventListener(TextBox textBox)
    {
        m_textBox = textBox;
        textBox.TextChanged += new EventHandler(textBox_TextChanged);
    }

    void textBox_TextChanged(object sender, EventArgs e)
    {
        // do something
    }

    public void Dispose()
    {
        m_textBox.TextChanged -= new EventHandler(textBox_TextChanged);
    }
}

class MyClass
{
    EventListener m_eventListener = null;
    TextBox m_textBox = new TextBox();

    void SetEventListener()
    {
        if (m_eventListener != null) m_eventListener.Dispose();
        m_eventListener = new EventListener(m_textBox);
    }
}
Run Code Online (Sandbox Code Playgroud)

在实际代码中,"EventListener"类涉及更多,每个实例都具有独特的重要性.我在集合中使用它们,并在用户点击时创建/销毁它们.


结论

我接受gbjbaanb的回答,至少目前如此.我觉得使用熟悉的界面的好处超过了在没有涉及非托管代码的情况下使用它的任何可能的缺点(这个对象的用户怎么会知道?).

如果有人不同意 - 请发帖/评论/编辑.如果可以对IDisposable做出更好的论证,那么我将改变接受的答案.

.net events idisposable unsubscribe

49
推荐指数
5
解决办法
2万
查看次数

我应该取消订阅活动吗?

我有3个关于事件的问题:

  1. 我应该总是取消订阅订阅的活动吗?
  2. 如果我不这样做会怎么样?
  3. 在下面的示例中,您将如何取消订阅订阅的活动?

我有这样的代码:

Ctor:目的:用于数据库属性更新

this.PropertyChanged += (o, e) =>
{
    switch (e.PropertyName)
    {
        case "FirstName": break;
        case "LastName": break;
    }
};
Run Code Online (Sandbox Code Playgroud)

这个:目的:用于GUI绑定将模型包装到视图模型中

ObservableCollection<Period> periods = _lpRepo.GetDailyLessonPlanner(data.DailyDate);
PeriodListViewModel = new ObservableCollection<PeriodViewModel>();

foreach (Period period in periods)
{
    PeriodViewModel periodViewModel = new PeriodViewModel(period,_lpRepo);
    foreach (DocumentListViewModel documentListViewModel in periodViewModel.DocumentViewModelList)
    {
        documentListViewModel.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);
        documentListViewModel.AddDocumentDelegate += new Action(OnAddDocument);
        documentListViewModel.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);
    }
    PeriodListViewModel.Add(periodViewModel);
}
Run Code Online (Sandbox Code Playgroud)

c# events unsubscribe subscribe

44
推荐指数
4
解决办法
4万
查看次数

Angular - DialogRef - 取消订阅 - 我是否需要取消订阅 afterClosed?

我的一位同事问我是否需要取消订阅对话框的 afterClosed() Observable。

我们使用 takeUntil 模式取消订阅 ngOnDestroy() 上的所有 Observable。

this.backEvent = fromEvent(window, 'popstate')
    .pipe(
        takeUntil(this.destroy$)
    )
    .subscribe(
        () => {
            this.navigationService.backClicked = true;
            this.navigationService.navigateBackToDirectoryCenter();
        }
    );
Run Code Online (Sandbox Code Playgroud)

ngOnDestroy()

ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
}
Run Code Online (Sandbox Code Playgroud)

那么是否有必要取消订阅 afterClosed() Observable 呢?

dialogRef.afterClosed().subscribe(
    (data) => {
            console.log(data);
        }
    },
);
Run Code Online (Sandbox Code Playgroud)

或者?

dialogRef.afterClosed()
    .pipe(
        takeUntil(this.destroy$)
    )
    .subscribe(
        (data) => {
            console.log(data);
        },
    );
Run Code Online (Sandbox Code Playgroud)

unsubscribe rxjs angular

35
推荐指数
3
解决办法
6621
查看次数

Angular2:取消订阅服务中的http observable

从http订阅中取消订阅Angular2服务的最佳做法是什么?

目前我这样做,但我不确定这是否是最好的方式.

import { Injectable } from "@angular/core";
import { Http } from "@angular/http";

import { Subject } from "rxjs/Subject";
import { ISubscription } from "rxjs/Subscription";

@Injectable()
export class SearchService {
    private _searchSource = new Subject<any>();

    public search$ = this._searchSource.asObservable();

    constructor(private _http: Http) {}

    public search(value: string) {
        let sub: ISubscription = this._http.get("/api/search?value=" + value)
            .map(response => <any>response.json())
            .do(data => this._searchSource.next(data))
            .finally(() => sub.unsubscribe()).subscribe();
    }

}
Run Code Online (Sandbox Code Playgroud)

unsubscribe rxjs5 angular

32
推荐指数
3
解决办法
1万
查看次数

Gmail取消订阅链接不会出现

在Gmail中,如果您收到来自新闻列表的电子邮件,则会在电子邮件地址旁边显示"取消订阅"链接,如下所示:

Google+ <noreply-67e4f7ae@plus.google.com> Unsubscribe
Run Code Online (Sandbox Code Playgroud)

标题名称List-Unsubscribe:标识了网址或电子邮件.

在Gmail中,我可以看到电子邮件原件以查看标题:

Received-SPF: pass (google.com: domain of root@domain.net designates 123.123.123.123 as permitted sender) client-ip=123.123.123.123;
Authentication-Results: mx.google.com;
   spf=pass (google.com: domain of root@domain.net designates 123.123.123.123 as permitted sender) smtp.mail=root@domain.net;
   dkim=pass header.i=@domain.com
List-Unsubscribe: <http://domain.com/uns.html?test=wdqwqw>
Run Code Online (Sandbox Code Playgroud)

我有List-Unsubscribe标题集,spf和dkim验证通过.

有什么不对?为什么gmail没有显示取消订阅链接?

email gmail unsubscribe

21
推荐指数
1
解决办法
7012
查看次数

取消订阅不是可观察的功能

我正在制作一个拖放应用程序,我创建了一个可观察鼠标位置,重新定位我的drag-object.

mouseMove$: any;

constructor(){
  this.mouseMove$ = Observable.fromEvent(document, 'mousemove')
    .do((mouseevent: MouseEvent) => {
      if (document.getElementById("drag-object")){
        document.getElementById("drag-object").style.left = (mouseevent.clientX) + 'px';
        document.getElementById("drag-object").style.top = (mouseevent.clientY) + 'px';
      }
  });
Run Code Online (Sandbox Code Playgroud)

通过这种实现,我可以通过这种方式订阅:

this.mouseMove$.subscribe();
Run Code Online (Sandbox Code Playgroud)

但我似乎无法取消订阅:

this.mouseMove$.unsubscribe();
Run Code Online (Sandbox Code Playgroud)

要么

this.mouseMove$.dispose();
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,我都会收到以下类型的错误:

TypeError:this.mouseMove $ .unsubscribe不是函数...

我不知道这是否与该做mouseMove$的类型any,但设置的类型,ObservableObservable<MouseEvent>没有工作.我在这里不理解什么?

unsubscribe observable typescript angular

17
推荐指数
1
解决办法
9975
查看次数

Angular RxJS Observable:takeUntil 与使用订阅取消订阅

有几种方法可以取消订阅 Angular 组件上的 observables(通过使用 ngOnDestroy)。应首选以下哪个选项?为什么(例如技术原因、性能等)?

选项 1:takeUntil

使用 RxJS takeUntil 取消订阅

@Component({
  selector: "app-flights",
  templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
  private readonly destroy$ = new Subject();

  public flights: FlightModel[];

  constructor(private readonly flightService: FlightService) {}

  ngOnInit() {
    this.flightService
      .getAll()
      .pipe(takeUntil(this.destroy$))
      .subscribe(flights => (this.flights = flights));
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Run Code Online (Sandbox Code Playgroud)

选项 2:.unsubscribe()

显式调用 .unsubscribe(),例如通过使用单独的订阅实例

@Component({
  selector: "app-flights",
  templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
  private readonly subscriptions = new Subscription();

  public flights: …
Run Code Online (Sandbox Code Playgroud)

unsubscribe observable rxjs angular

17
推荐指数
2
解决办法
1万
查看次数

防止电子邮件扫描器激活“取消订阅”链接的策略

我想在我的服务发送的电子邮件的页脚中提供一个单击“取消订阅”链接。

显然,许多垃圾邮件扫描程序会扫描电子邮件,并会按照电子邮件中的任何链接扫描其内容中的恶意软件。到目前为止我使用的解决方法:

  • 如果“取消订阅”页面是通过 HTTP GET 请求的,它会呈现一个简单的确认表单和一些在页面加载时提交表单的 JS
  • 如果“取消订阅”页面是通过 HTTP POST 请求的,那么我们取消订阅用户

这样,用户通常只需要单击表单,他们就会收到“您已取消订阅”的消息。如果他们禁用了 JS,他们仍然可以手动提交确认表。

现在的问题是,像Office365的ATP这样的扫描器会打开页面,并在其中执行JS。通过执行 JS,他们提交表单并导致用户自动取消订阅。

我已经考虑向自动提交 JS 逻辑添加检查:

  • 不要为特定的用户代理自动提交
  • 不要自动提交特定的客户端 IP 范围
  • 触发鼠标移动事件的自动提交

但这些似乎都是脆弱的方法,充其量是黑客攻击,随着电子邮件扫描仪改变他们的策略,这些方法必然会被破坏。

我相信这个问题在我之前有很多人。除了放弃单击功能之外,是否有已知的合理解决方法?

附注。我已经添加了对RFC 8058 的支持,但用户仍然会点击页脚中的链接。

email spam unsubscribe office365

13
推荐指数
1
解决办法
1046
查看次数

为您的简报实施取消订阅链接的最佳方式是什么?

我在想我在unsubscribe链接中创建一个停用代码及其用户ID.然后,当我的时事通讯的收件人点击该链接时,我可以查找他们的用户ID并查看停用代码是否匹配.

这听起来像是最好的方式吗?

还有什么其他方法?

email newsletter unsubscribe

9
推荐指数
2
解决办法
7776
查看次数

取消订阅通过ref关键字传递给委托方法的委托?

我有以下课程:

public class Terminal : IDisposable
{
    readonly List<IListener> _listeners;

    public Terminal(IEnumerable<IListener> listeners)
    {
        _listeners = new List<IListener>(listeners);
    }

    public void Subscribe(ref Action<string> source)
    {
        source += Broadcast;
        //Store the reference somehow?
    }

    void Broadcast(string message)
    {
        foreach (var listener in _listeners) listener.Listen(message);
    }

    public void Dispose()
    {
        //Unsubscribe from all the stored sources?
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经搜索了一段时间,似乎无法存储使用ref关键字传递的参数.尝试将源参数添加到列表或将其分配给字段变量不允许它保持对实际委托的原始引用的引用; 所以我的问题是:

  • 有没有办法取消订阅所有来源而不再传递他们的参考?
  • 如果没有,为了支持它,如何更改类,但仍然通过一个方法传递委托来维护订阅?
  • 是否有可能在不使用Reflection的情况下实现它?
  • 是否有可能在没有将委托/事件包装在类中然后将类作为订阅参数传递的情况下实现它?

谢谢.

编辑:似乎没有使用包装器或反射,没有解决给定的问题.我的目的是使类尽可能地可移植,而不必将代理包装在辅助类中.谢谢大家的贡献.

c# parameters delegates ref unsubscribe

9
推荐指数
1
解决办法
470
查看次数