Thursday, May 5, 2011

My first Rx Attempt revisited

I have recently rediscovered my custom code analysis rules which included one that no longer compiles. The Rx team has made sweeping and breaking changes to the structure and namespaces in Rx. How difficult was the code update? 2 references removed, 1 added, and a single MethodName changed.

I cleaned up the code, and discovered many improvements along the way.
I do wish I could find a cleaner way to do this:

var whenMethodsFound = Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
 act => foundMethods.CollectionChanged += act,
  act => foundMethods.CollectionChanged -= act);

Idea:
Add a mapping extension in extension method class
Great for simple on the go, but manual for every class you want to do this with.

Which would look like this

public static IObservable<IEvent<PageEventArgs>> GetPublishingPageEvent(this DataFactory dataFactory)
   {
       return Observable.FromEvent((EventHandler<PageEventArgs> h) => new PageEventHandler(h), 
                                h => dataFactory.PublishingPage += h, 
                                h => dataFactory.PublishingPage -= h);
  }





public override ProblemCollection Check(TypeNode type)
    {
      Debug.WriteLine("Checking type:"+type.FullName);
      var initializer = type.Members.OfType<Method>( ).FirstOrDefault(x => x.FullName==type.FullName+".InitializeComponent");

      if (initializer==null)
        return null;
      Debug.WriteLine(initializer.FullName);
      var constructorsWithNoInitCall = type.Members.OfType<Method>( ).Where(m => m.NodeType==NodeType.InstanceInitializer).ToList( );
      var visitedMethods = new HashSet<string>( );
      var foundMethods = new ObservableHashSet<Method>( );
      var whenMethodsFound = Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(act => foundMethods.CollectionChanged += act,act => foundMethods.CollectionChanged -= act);
      whenMethodsFound.Where(e=>e.EventArgs.Action==NotifyCollectionChangedAction.Add).Select(x=>x.EventArgs)
      .Subscribe(
        e =>
        {
            
              if (constructorsWithNoInitCall.Any( ))
                Parallel.ForEach(e.NewItems.Cast<Method>( ).Where(m => visitedMethods.Any(v => v==m.FullName)==false),
                  i =>
                  {

                    lock (visitedMethods)
                    {
                      if (visitedMethods.Contains(i.FullName))
                        return;
                      visitedMethods.Add(i.FullName);

                    }
                    Debug.WriteLine("Visiting:"+i.FullName);
                    var callers = (CallGraph.CallersFor(i));
                    constructorsWithNoInitCall.RemoveAll(x => callers.Any(c => x.FullName==c.FullName));
                    if (constructorsWithNoInitCall.Any( ))
                      foreach (var item in callers.Where(c => visitedMethods.Any(v => v==c.FullName)==false))
                      {
                        foundMethods.Add(item);
                      }
                  });
             
          
        }
        );
      foundMethods.Add(initializer);


      ReportProblem(constructorsWithNoInitCall, type);

      return Problems;
    }

No comments:

Post a Comment