Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 为什么我对接口的TCollections.CreateObservableList的实现不起作用?_Delphi_Spring4d - Fatal编程技术网

Delphi 为什么我对接口的TCollections.CreateObservableList的实现不起作用?

Delphi 为什么我对接口的TCollections.CreateObservableList的实现不起作用?,delphi,spring4d,Delphi,Spring4d,我试图按照@Stefan Glienke在接口的可观察列表中的建议实现 这个版本应该实现一个可观察的接口列表。编译,但在运行时找不到“更改”事件处理程序。 我将一些过程参数从TObject更改为IInterface。 由于基类中的实现,其他一些必须是TObject 谢谢你的帮助 此示例显示了以下行为: program Project62; {$APPTYPE CONSOLE} uses Spring, Spring.Events, Spring.Collections, Sp

我试图按照@Stefan Glienke在接口的可观察列表中的建议实现

这个版本应该实现一个可观察的接口列表。编译,但在运行时找不到“更改”事件处理程序。 我将一些过程参数从TObject更改为IInterface。 由于基类中的实现,其他一些必须是TObject

谢谢你的帮助

此示例显示了以下行为:

program Project62;

{$APPTYPE CONSOLE}

uses
  Spring,
  Spring.Events,
  Spring.Collections,
  Spring.Collections.Lists,
  SysUtils;

type
  // Like TObservableList but for interfaces not classes
  TObservableInterfaceList<T: IInterface> = class(TFoldedInterfaceList<T>, INotifyPropertyChanged)
  private
    fOnPropertyChanged: IEvent<TPropertyChangedEvent>;
    function GetOnPropertyChanged: IEvent<TPropertyChangedEvent>;
  protected
    // Sender must be TObject because of TPropertyChangedEvent
    procedure DoItemPropertyChanged(sender: TObject; const eventArgs: IPropertyChangedEventArgs);

    procedure DoPropertyChanged(const propertyName: string);
    procedure Changed(const value: IInterface; action: TCollectionChangedAction); override;
  public
    constructor Create; override;
    property OnPropertyChanged: IEvent<TPropertyChangedEvent> read GetOnPropertyChanged;
  end;

  TNotifyPropertyChangedBase = class(TInterfaceBase, INotifyPropertyChanged)
  private
    fOnPropertyChanged: Event<TPropertyChangedEvent>;
    function GetOnPropertyChanged: IPropertyChangedEvent;
  protected
    procedure PropertyChanged(const propertyName: string);
  end;

  IMyInterface = interface(IInterface)
    ['{D5966D7D-1F4D-4EA8-B196-CB9B39AF446E}']
    function GetName: String;
    procedure SetName(const Value: String);
    property Name: String read GetName write SetName;
  end;

  TMyInterfacedObject = class(TNotifyPropertyChangedBase, IMyInterface)
  private
    FName: string;
    function GetName: string;
    procedure SetName(const Value: string);
  public
    property Name: string read GetName write SetName;
  end;

  TMain = class
    procedure ListOfMyInterfaceChanged(Sender: TObject; const item: IMyInterface; action: TCollectionChangedAction);
  end;

constructor TObservableInterfaceList<T>.Create;
begin
  inherited Create;
  fOnPropertyChanged := TPropertyChangedEventImpl.Create;
end;

// Sender must be TObject because of TPropertyChangedEvent
procedure TObservableInterfaceList<T>.DoItemPropertyChanged(sender: TObject; const eventArgs: IPropertyChangedEventArgs);
var
  MyInterface: IMyInterface;
begin
  if Supports(sender, IMyInterface, MyInterface) then
    inherited Changed(MyInterface, caChanged);
end;

procedure TObservableInterfaceList<T>.DoPropertyChanged(const propertyName: string);
begin
  if Assigned(fOnPropertyChanged) and fOnPropertyChanged.CanInvoke then
    fOnPropertyChanged.Invoke(Self,
      TPropertyChangedEventArgs.Create(propertyName) as IPropertyChangedEventArgs);
end;

function TObservableInterfaceList<T>.GetOnPropertyChanged: IEvent<TPropertyChangedEvent>;
begin
  Result := fOnPropertyChanged;
end;

procedure TObservableInterfaceList<T>.Changed(const value: IInterface; action: TCollectionChangedAction);
var
  notifyPropertyChanged: INotifyPropertyChanged;
  propertyChanged: IEvent<TPropertyChangedEvent>; // TPropertyChangedEvent = procedure(Sender: TObject; const EventArgs: IPropertyChangedEventArgs) of object;

begin
  if Supports(value, INotifyPropertyChanged, notifyPropertyChanged) then
  begin
    propertyChanged := notifyPropertyChanged.OnPropertyChanged;
    case action of
      caAdded:
        propertyChanged.Add(DoItemPropertyChanged);
      caRemoved, caExtracted:
        propertyChanged.Remove(DoItemPropertyChanged);
    end;
  end;
   inherited Changed(value, action);
  DoPropertyChanged('Count');
end;

function TNotifyPropertyChangedBase.GetOnPropertyChanged: IPropertyChangedEvent;
begin
  Result := fOnPropertyChanged;
end;

procedure TNotifyPropertyChangedBase.PropertyChanged(const propertyName: string);
begin
  fOnPropertyChanged.Invoke(Self, TPropertyChangedEventArgs.Create(propertyName) as IPropertyChangedEventArgs);
end;

procedure TMyInterfacedObject.SetName(const Value: string);
begin
  FName := Value;
  PropertyChanged('Name');
end;

function TMyInterfacedObject.GetName: string;
begin
  Result := FName;
end;

procedure TMain.ListOfMyInterfaceChanged(Sender: TObject; const item: IMyInterface; action: TCollectionChangedAction);
begin
  case action of
    caAdded: Writeln('item added: ', item.Name);
    caRemoved, caExtracted: Writeln('item removed: ', item.Name);
    caChanged: Writeln('item changed: ', item.Name);
  end;
end;

var
  main: TMain;
  iListOfMyInterface: IList<IMyInterface>;
  MyInterfacedObject: TMyInterfacedObject;
begin
  iListOfMyInterface := TCollections.CreateInterfaceList<IMyInterface>;
  iListOfMyInterface.OnChanged.Add(main.ListOfMyInterfaceChanged);
  MyInterfacedObject := TMyInterfacedObject.Create;
  MyInterfacedObject.Name := 'MyInterfacedObject';
  iListOfMyInterface.Add(MyInterfacedObject);
  iListOfMyInterface.first.Name := 'MyInterfacedObject hit the change event';
  Readln;
end.
程序项目62;
{$APPTYPE控制台}
使用
春天
春天,事件,
春季系列,
Spring.Collections.list,
SysUtils;
类型
//类似于TObservableList,但用于接口而不是类
TObservableInterfaceList=class(TFoldedInterfaceList,INotifyPropertyChanged)
私有的
fOnPropertyChanged:IEvent;
函数GetOnPropertyChanged:IEEvent;
受保护的
//由于TPropertyChangedEvent,发件人必须为ToObject
过程DoItemPropertyChanged(发送方:ToObject;常量事件参数:IPropertyChangedEventArgs);
过程DoPropertyChanged(constPropertyName:string);
过程已更改(常量值:界面;操作:TCollectionChangedAction);推翻
公众的
构造函数创建;推翻
属性OnPropertyChanged:IEEvent读取GetOnPropertyChanged;
结束;
TNotifyPropertyChangedBase=class(TInterfaceBase,INotifyPropertyChanged)
私有的
fOnPropertyChanged:事件;
函数GetOnPropertyChanged:IPropertyChangedEvent;
受保护的
过程PropertyChanged(constPropertyName:string);
结束;
IMyInterface=接口(i接口)
[{D5966D7D-1F4D-4EA8-B196-CB9B39AF446E}]
函数GetName:String;
过程集合名(常量值:字符串);
属性名称:字符串读取GetName写入SetName;
结束;
TMyInterfacedObject=class(TNotifyPropertyChangedBase,IMyInterface)
私有的
FName:字符串;
函数GetName:string;
过程集合名(常量值:字符串);
公众的
属性名称:字符串读取GetName写入SetName;
结束;
TMain=类
MinInterfaceChanged的过程列表(发送方:ToObject;常量项:IMyInterface;操作:TCollectionChangedAction);
结束;
构造函数TObservableInterfaceList.Create;
开始
继承创造;
fOnPropertyChanged:=TPropertyChangedEventImpl.Create;
结束;
//由于TPropertyChangedEvent,发件人必须为ToObject
过程ToServableInterfaceList.DoItemPropertyChanged(发送方:ToObject;常量事件参数:IPropertyChangedEventArgs);
变量
MyInterface:IMyInterface;
开始
如果支持(发送方、IMyInterface、MyInterface),则
继承的已更改(MyInterface,caChanged);
结束;
过程toServableInterfaceList.DoPropertyChanged(constPropertyName:string);
开始
如果已分配(fOnPropertyChanged)和fOnPropertyChanged.CanInvoke,则
fOnPropertyChanged.Invoke(Self,
TPropertyChangedEventArgs.Create(propertyName)作为IPropertyChangedEventArgs);
结束;
函数TObservableInterfaceList.GetOnPropertyChanged:IEEvent;
开始
结果:=fOnPropertyChanged;
结束;
过程ToServableInterfaceList.Changed(常量值:IInterface;操作:TCollectionChangedAction);
变量
notifyPropertyChanged:INotifyPropertyChanged;
属性更改:IEvent;//TPropertyChangedEvent=对象的过程(发送方:TObject;const-EventArgs:IPropertyChangedEventArgs);
开始
如果支持(值、INotifyPropertyChanged、notifyPropertyChanged),则
开始
propertyChanged:=notifyPropertyChanged.OnPropertyChanged;
案例诉讼
加上:
添加(DoItemPropertyChanged);
CAREMOVE,CARETRACTED:
propertyChanged.Remove(DoItemPropertyChanged);
结束;
结束;
继承的更改(值、操作);
DoPropertyChanged(“计数”);
结束;
函数TNotifyPropertyChangedBase.GetOnPropertyChanged:IPropertyChangedEvent;
开始
结果:=fOnPropertyChanged;
结束;
过程TNotifyPropertyChangedBase.PropertyChanged(constPropertyName:string);
开始
调用(Self,TPropertyChangedEventArgs.Create(propertyName)作为IPropertyChangedEventArgs);
结束;
过程TMyInterfacedObject.SetName(常量值:字符串);
开始
FName:=值;
财产变更(“名称”);
结束;
函数TMyInterfacedObject.GetName:string;
开始
结果:=FName;
结束;
过程TMain.ListofMyInterface已更改(发送方:ToObject;常量项:IMyInterface;操作:TCollectionChangedAction);
开始
案例诉讼
caAdded:Writeln('item added:',item.Name);
caRemoved,caExtracted:Writeln('item removed:',item.Name);
更改:Writeln('item changed:',item.Name);
结束;
结束;
变量
主要:TMain,;
iListOfMyInterface:IList;
MyInterfacedObject:TMyInterfacedObject;
开始
iListOfMyInterface:=TCollections.CreateInterfaceList;
iListOfMyInterface.OnChanged.Add(main.ListOfMyInterfaceChanged);
MyInterfacedObject:=TMyInterfacedObject.Create;
MyInterfacedObject.Name:=“MyInterfacedObject”;
添加(MyInterfacedObject);
iListOfMyInterface.first.Name:=“MyInterfacedObject命中更改事件”;
Readln;
结束。

因为您从未在代码中创建
TObservableInterfaceList
,但是:

iListOfMyInterface := TCollections.CreateInterfaceList<IMyInterface>;
iListOfMyInterface:=TCollections.CreateInterfaceList;
正确:

iListOfMyInterface := TObservableInterfaceList<IMyInterface>.Create;
iListOfMyInterface:=TObservableInterfaceList.Create;
您的
DoItemPropertyChanged
实现也存在缺陷。您在这里引用了一种特殊的接口类型,但实际上必须将sender向下传递为T,因为这是lists元素类型

<>我会考虑把这个添加到框中2。