/// <summary> /// Subscribes to the data produced by the <see cref="IDataLoader"/> in order to update its state without reloading the <see cref="IDataLoader"/>. /// </summary> /// <remarks> /// This makes sense when <typeparamref name="TData"/> is something observable such as <see cref="INotifyCollectionChanged"/>. /// </remarks> /// <typeparam name="TData">The type of data.</typeparam> /// <param name="builder">The builder.</param> /// <param name="subscribeToData"> /// The method subscribing to the data. /// Use that method to subscribe to events available on <typeparamref name="TData"/> and return an IDisposable that unsubscribes from events. /// Your event handlers should leverage <see cref="IDataLoaderSetter.SetData(object)"/> and <see cref="IDataLoaderSetter.SetError(Exception)"/>. /// </param> /// <returns>The original <paramref name="builder"/>.</returns> public static IDataLoaderBuilder <TData> SubscribeToData <TData>( this IDataLoaderBuilder <TData> builder, Func <TData, IDataLoaderSetter, IDisposable> subscribeToData) { var namePrefix = builder.Name == null ? string.Empty : builder.Name + "."; var trigger = new SubscribeToDataTrigger(namePrefix + nameof(SubscribeToDataTrigger)); var strategy = new SubscribeToDataStrategy(data => subscribeToData((TData)data, trigger)); return(builder .WithTrigger(trigger) .WithStrategy(strategy)); }
/// <summary> /// Tries to subscribe to the data produced by the <see cref="IDataLoader"/> in order to update its state without reloading the <see cref="IDataLoader"/>. /// </summary> /// <remarks> /// This makes sense when <typeparamref name="TData"/> is something observable such as <see cref="INotifyCollectionChanged"/>. /// You should use this method with <see cref="DataLoaderBuilderFactory.DataLoaderBuilderFactory(Func{IDataLoaderBuilder, IDataLoaderBuilder})"/> so that all DataLoaders of <typeparamref name="TData"/> subscribe to their data automatically. /// </remarks> /// <typeparam name="TData">The type of data.</typeparam> /// <param name="builder">The builder.</param> /// <param name="subscribeToData"> /// The method subscribing to the data. /// Use that method to subscribe to events available on <typeparamref name="TData"/> and return an IDisposable that unsubscribes from events. /// Your event handlers should leverage <see cref="IDataLoaderSetter.SetData(object)"/> and <see cref="IDataLoaderSetter.SetError(Exception)"/>. /// </param> /// <returns>The original <paramref name="builder"/>.</returns> public static IDataLoaderBuilder TrySubscribeToData <TData>( this IDataLoaderBuilder builder, Func <TData, IDataLoaderSetter, IDisposable> subscribeToData) { // Early-out 1: The SubscribeToData delegating strategy is already present in the builder. if (builder.DelegatingStrategies.Any(s => s is SubscribeToDataStrategy)) { return(builder); } // Early-out 2: The builder isn't typed. if (builder.DataType == null) { if (typeof(SubscribeToDataExtensions).Log().IsEnabled(LogLevel.Error)) { typeof(SubscribeToDataExtensions).Log().LogError("Can't validate type. Make sure the 'IDataLoaderBuilder.DataType' property is set before calling 'TrySubscribeToData'."); } return(builder); } var dataType = typeof(TData); // Early-out 3: The builder type doesn't match TData. if (!dataType.IsAssignableFrom(builder.DataType)) { // If TData doesn't match the builder type, we don't do anything. return(builder); } var namePrefix = builder.Name == null ? string.Empty : builder.Name + "."; var trigger = new SubscribeToDataTrigger(namePrefix + nameof(SubscribeToDataTrigger)); var strategy = new SubscribeToDataStrategy(data => subscribeToData((TData)data, trigger)); return(builder .WithTrigger(trigger) .WithStrategy(strategy)); }