hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Implementing interface with events

Last post 10-11-2007, 8:17 by gneverov. 3 replies.
Sort Posts: Previous Next
  •  10-10-2007, 1:24 3734

    Implementing interface with events

    I can't figure out how to implement an interface with .NET-compatible events (e.g. IBindingList). As far as I understand, there's some "compiler magic", which turns public non-virtual properties of type IHandlerEvent into CLI events visible to other .NET languages and everything works fine unless the property is a member of interface. Otherwise the compiler complains that there's no such property "ListChangedEvent" to override and two methods "add_ListChangedEvent" and "remove_ListChangedEvent" are not implemented. So is there a way to implement .NET interfaces with events in F#?
  •  10-10-2007, 3:22 3735 in reply to 3734

    Re: Implementing interface with events

    Yes the correct way seems to be to override the add and remove methods. Belows an implemntation of binding list that compiles, but obviously isn't correct. To invoke then event you need to iterate though the handlers collection and invoke each event handler that you find, obviously not ideal, there maybe a better way to do this. I think this is because interfaces that contain event are relatively rare, and have probably been a bit overlooked. I would _guess_ this is one area that maybe improved in the future.

    Also not that it is alot easier to expose an event from a class. All you need to do is expose the a value create via IEvent.create_HandlerEvent, yes there is some compiler magic to make events first class values in F#. More details here: http://blogs.msdn.com/dsyme/archive/2006/03/24/559582.aspx

    open System.ComponentModel

    type BindingList() = class
        let handlers  = new ResizeArray<ListChangedEventHandler>()
        interface IBindingList with
            member x.remove_ListChanged(eh : ListChangedEventHandler) = handlers.Remove(eh) |> ignore
            member x.add_ListChanged(eh : ListChangedEventHandler) = handlers.Add(eh)
            member x.AddIndex(prop : PropertyDescriptor) = ()
            member x.AddNew() = (null :obj)
            member x.ApplySort(prop : PropertyDescriptor, direction : ListSortDirection) = ()
            member x.Find(prop : PropertyDescriptor, key : obj ) = 0
            member x.RemoveIndex(prop : PropertyDescriptor ) = ()
            member x.RemoveSort() = ()
            member x.AllowEdit
                with  get() = true
            member x.AllowNew
                with  get() = true
            member x.AllowRemove
                with  get() = true
            member x.IsSorted
                with  get() = true
            member x.SortDirection
                with  get() = ListSortDirection.Ascending
            member x. SortProperty
                with  get() = (null: PropertyDescriptor)
            member x.SupportsChangeNotification
                with  get() = true
            member x.SupportsSearching
                with  get() = true
            member x.SupportsSorting
                with  get() = true
            member x.Add(value:obj) = 0;
            member x.Clear() = ()
            member x.Contains(value:obj) = true
            member x.IndexOf(value:obj) = 0
            member x.Insert(index : int , value: obj) =()
            member x.Remove(value : obj) = ()
            member x.RemoveAt(index : int) = ()
            member x.IsFixedSize
                with get() = true
            member x.IsReadOnly
                with get() = true
            member x.Item
                with get(i : int) = null
                and set (i: int) (o : obj) =()
            member x.CopyTo(array : System.Array, index : int ) =()
            member x.Count
                with  get() = 0
            member x.IsSynchronized
                with get() = true
            member x.SyncRoot
                with get() = new obj()       
            member x.GetEnumerator() = (null: System.Collections.IEnumerator)
        end
    end


    Robert Pickering, MVP
    http://strangelights.com
  •  10-10-2007, 12:16 3738 in reply to 3735

    Re: Implementing interface with events

    Thanks, Robert
    I knew that the hard way is the way to go ;-)
    I've just been hoping there's some hidden nice and smart solution.
  •  10-11-2007, 8:17 3740 in reply to 3735

    Re: Implementing interface with events

    You do not need to have a collection of delegates since delegates are "multicast" by default. E.g.,

    type BindingList() = class
        let mutable handler : ListChangedEventHandler = null
        interface IBindingList with
            member x.remove_ListChanged(eh : ListChangedEventHandler) = handler <- (Delegate.Remove(handler, eh) :?> ListChangedEventHandler)
            member x.add_ListChanged(eh : ListChangedEventHandler) = handler <- (Delegate.Combine(handler, eh) :?> ListChangedEventHandler)
            member x.Clear() = match handler with null -> () | _ -> handler.Invoke(x, null)

View as RSS news feed in XML
Powered by Community Server, by Telligent Systems