Check if an AsyncSubject hasn't fired - system.reactive

AsycSubject<Unit>() sub;
// stuff
if(!sub.HasFired())
// Do stuff
Current best attempt is:
public static bool HasFired<T>(this AsyncSubject<T> sub)
{
AsyncSubject<bool> ret = new AsyncSubject<bool>();
sub.Timeout(TimeSpan.FromMilliseconds(20))
.Subscribe(_ =>
{
ret.OnNext(true);
ret.OnCompleted();
},
ex =>
{
ret.OnNext(false);
ret.OnCompleted();
});
return ret.First();
}
But it feels very ugly and long. I suspect I'm missing something simple. Any suggestions?

It's easier to wrap around the existing AsyncSubject and add the required state.
public class AsyncSubjectEx<T> : ISubject<T>, IDisposable
{
AsyncSubject<T> Subject = new AsyncSubject<T>();
public bool HasValue { get; protected set; }
public object Gate = new object();
public void OnCompleted()
{
Subject.OnCompleted();
}
public void OnError(Exception error)
{
Subject.OnError(error);
}
public void OnNext(T value)
{
lock (Gate)
{
Subject.OnNext(value);
HasValue = true;
}
}
public IDisposable Subscribe(IObserver<T> observer)
{
lock (Gate)
return Subject.Subscribe(observer);
}
public void Dispose()
{
Subject.Dispose();
}
}
Ironically, the original AsyncSubject upon reflection shows that there is a hasValue field, but it doesn't happen to be exposed. Consider reporting this to the Rx team - might be useful sometime.

Related

Prism proper handling of viewmodel collections

I'm using the prism framework for my Xamarin.Forms application.
This is a common scenario, but it caused me headache.
MainPage
- MainPageViewModel
- ObserveableCollection<SomePageViewModel>
public class MainPageViewModel : BaseViewModel
{
private ObservableCollection<SomePageViewModel> viewModels;
public MainPageViewModel(INavigationService navigationService) : base(navigationService)
{
SomePageSelectedCommand = DelegateCommand.FromAsyncHandler(NavigateToSomePage);
}
public ICommand SomePageSelectedCommand { get; private set; }
public ObservableCollection<SomePageViewModel> ViewModels
{
get { return viewModels; }
set { SetProperty(ref viewModels, value); }
}
private async Task NavigateToSomePage(SomePageViewModel viewModel)
{
var navParams = new NavigationParameters
{
{viewModel.typeof(SomePageViewModel).Name, viewModel}
};
await Navigation.NavigateAsync(NavigationConstants.SomePageUri, navParams, false);
}
}
public class SomePageViewModel : BaseViewModel
{
protected SomeModel someModel;
public SomePageViewModel(INavigationService navigationService) : base(navigationService)
{
someModel = new SomeModel();
EditCommand = DelegateCommand.FromAsyncHandler(Edit);
}
public ICommand EditCommand { get; private set; }
public string Name
{
get { return SomeModel.Name; }
set { SetProperty(ref SomeModel.Name, value); }
}
public string Description
{
get { return SomeModel.Description; }
set { SetProperty(ref SomeModel.Description, value); }
}
public override void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters.ContainsKey(typeof(SomePageViewModel).Name))
{
var viewModel = (SomePageViewModel)parameters[typeof(SomePageViewModel).Name];
Name = viewModel.Name;
Description = viewModel.Name;
}
}
private async Task Edit()
{
var navParams = new NavigationParameters
{
{viewModel.typeof(SomePageViewModel).Name, this}
};
await Navigation.NavigateAsync(NavigationConstants.SomePageEditUri, navParams, false);
}
}
public class SomePageEditViewModel : BaseViewModel
{
public SomePageEditViewModel(INavigationService navigationService) : base(navigationService)
{
SaveCommand = DelegateCommand.FromAsyncHandler(Save);
}
public ICommand SaveCommand { get; private set; }
private async Task Save()
{
App.ContentService.Save(someModel);
await Navigation.GoBackAsync();
}
}
So lets navigate from the MainPage to a SomePage. We want to edit it so we navigate to SomePageEdit afterwards and save finally.
What is a proper way to make the changes visible to the SomePage and the MainPage according mvvm/prsim? For the first one I could pass the changes as NavigationParameter into GoBackAsync. But what about the MainPage?
Well it appears you have a bit of a design problem. To properly architect your app you want something closer to:
Model
public class TodoItem : ObservableObject
{
private string _name;
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
private bool _done;
public bool Done
{
get { return _done; }
set { SetProperty(ref _done, value); }
}
}
Model Collection Page ViewModel
public class TodoItemListPageViewModel : BaseViewModel, INavigationAware
{
private INavigationService _navigationService { get; }
public TodoItemListViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
TodoItems = new ObservableRangeCollection<TodoItem>();
AddTodoItemCommand = new DelegateCommand(OnAddTodoItemCommandExecuted);
EditTodoItemCommand = new DelegateCommand<TodoItem>(OnEditTodoItemCommandExecuted);
}
public ObservableRangeCollection<TodoItem> TodoItems { get; }
public DelegateCommand AddTodoItemCommand { get; }
public DelegateCommand<TodoItem> EditTodoItemCommand { get; }
public void OnNavigatingTo(NavigationParameters parameters)
{
// Initialize your collection
}
public void OnNavigatedTo(NavigationParameters parameters)
{
if(parameters.GetValue<NavigationMode>(KnownNavigationParameters.NavigationMode) == NavigationMode.Back)
{
// Option 1
// Fetch an updated list of TodoItems from your data source
TodoItems.ReplaceRange(updatedTodoItems);
// Option 2
// Replace the updated item or add a new item
}
}
Edit Model Page ViewModel
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
private async void OnAddTodoItemCommandExecuted() =>
await _navigationService.NavigateAsync("AddTodoItemPage");
private async void OnEditTodoItemCommandExecuted(TodoItem item) =>
await _navigationService.NavigateAsync("EditTodoItemPage", new NavigationParameters { { "item", item } });
}
public class EditTodoItemPageViewModel : BaseViewModel
{
private INavigationService _navigationService { get; }
public EditTodoItemPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
SaveCommand = new DelegateCommand(OnSaveCommandExecuted, () => IsNotBusy)
.ObservesProperty(() => IsBusy);
}
private TodoItem _model;
public TodoItem Model
{
get { return _model; }
set { SetProperty(ref _model, value); }
}
public DelegateCommand SaveCommand { get; }
public void OnNavigatingTo(NavigationParameters parameters)
{
Model = parameters.GetValue<TodoItem>("item");
}
private async void OnSaveCommandExecuted()
{
IsBusy = true;
// Persist any changes
// Option 1
await _navigationService.GoBackAsync();
// Option 2
await _navigationService.GoBackAsync(new NavigationParameters { { "updatedItem", Model } });
IsBusy = false;
}
}
The Why...
Your ObservableCollection should be where T : TModel not where T : TViewModel. Another issue you would have immediately is that the INavigationService is dependent on knowing what Page you're navigating to/from. So you cannot follow the pattern you're doing there.
Now a couple of notes here.
You'll notice this sample is actually using some helpers from the MvvmHelpers library. The BaseViewModel class from that library gives you the IsBusy/IsNotBusy property as well as a Title property and the ObservableRangeCollection.
ObservableRangeCollection vs ObservableCollection
The ObservableRangeCollection gives you a little better performance particularly when working with larger datasets. You may have noticed the Option 1 where we simply get the updated dataset and replace the entire dataset. This is where the ObservableRangeCollection really shines in my opinion since you're able to ensure you have an up to date dataset while minimizing the notifications to the UI resulting in fewer CPU cycles taken up.
Models, Views, ViewModels
I do not mean for this to an authoritative answer but to at least provide food for thought. From a high level overview of MVVM patterns you generally are working with a View which provides the UX, a ViewModel which provides the business logic for who/what/why/when/where/etc, and a Model which is the data we want to work with. In some cases it can become necessary to introduce a DTO which further abstracts our raw data from the Model we want to work with as a logical unit.

How to Create Lookup by Account Type using DimensionDynamicAccountController?

I have a problem.
I have in my new table two new fields
1) Name -> AccountNum, EDT--> DimensionDynamicAccount
2) Name -> AccountType, EDT--> LedgerJournalACType
class declaration
:
public class FormRun extends ObjectRun
{
DimensionDynamicAccountController dimAccountController;
}
init (for the form):
public void init()
{
super();
dimAccountController = DimensionDynamicAccountController::construct(
MyTable_ds,
fieldstr(MyTable, LedgerDimension),
fieldstr(MyTable, AccountType));
}
4. Override the following methods on the Segmented Entry control instance in the form design.
public void jumpRef()
{
dimAccountController.jumpRef();
}
public void loadAutoCompleteData(LoadAutoCompleteDataEventArgs _e)
{
super(_e);
dimAccountController.loadAutoCompleteData(_e);
}
public void segmentValueChanged(SegmentValueChangedEventArgs _e)
{
super(_e);
dimAccountController.segmentValueChanged(_e);
}
public void loadSegments()
{
super();
dimAccountController.parmControl(this);
dimAccountController.loadSegments();
}
public boolean validate()
{
boolean isValid;
isValid = super();
isValid = dimAccountController.validate() && isValid;
return isValid;
}
5. Override the following methods on the data source field that backs the Segmented Entry control.
public Common resolveReference(FormReferenceControl _formReferenceControl)
{
return dimAccountController.resolveReference();
}
Now my problem is Lookup only works for AccountType=="Ledger" not for customer, Vendor etc...
If I have a AccountType == Vendor or similant but different to Ledger I see this
I would want to have same the same thing that's in the LedgerJournalTrans Form
There is a solution,
thanks all,
enjoy
This might be too obvious, but I think you're missing the lookup() method.
See:
\Forms\LedgerJournalTransDaily\Designs\Design\[Tab:Tab]\[TabPage:OverViewTab]\[Grid:overviewGrid]\SegmentedEntry:LedgerJournalTrans_AccountNum\Methods\lookup
public void lookup()
{
if (!ledgerJournalEngine.accountNumLookup(ledgerJournalTrans_AccountNum,
ledgerJournalTrans,
ledgerJournalTrans.OffsetAccountType,
ledgerJournalTrans.parmOffsetAccount(),
ledgerJournalTrans_Asset))
{
super();
}
}

Troubles with dependency injection

I am working on an ASP.NET WebAPI using OWIN. To manage the instances of DBContext (Entity Framework), I try to use Ninject. However, when I call a controller, the programm returns an error:
The controller cannot be created, missing constructor.
Could you tell me what is going wrong here?
My Controller Class:
public class Testcontroller
{
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context)
{
_context = context;
}
}
This is the Ninject-File:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IApplicationDbContext>().To<ApplicationDbContext>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
}
}
Ninject Dependency Scope:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
// This class is the resolver, but it is also the global scope
// so we derive from NinjectScope.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel) : base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
The Entity Framework DbContext-Class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<Models.Team> Teams { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public interface IApplicationDbContext
{
DbSet<Models.Team> Teams { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
I tried to follow this tutorial: http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
What have I done wrong here?
Thanks in advance!
Unless there was a serious omission in you controller code, your controller is not inheriting from ApiController, as is expected with Web Api
public class TestController : ApiController {
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context) {
_context = context;
}
}
UPDATE
I tried to set up everything from scratch using this: http://www.alexzaitzev.pro/2014/11/webapi2-owin-and-ninject.html
For some reason, it now works out perfectly fine.
Thank you for your support!

Instance in Caliburn Micro

We are using Caliburn Micro for the first time.
We have a AppBootstrapper inherited from ShellViewModel.
Situvation is that VieModels should have the same instance unless it is reset.
we are able to achieve shared or not shared everytime, but releasing the export whenever needed is still a mystery.
public class AppBootstrapper : Bootstrapper<ShellViewModel>
{
private static CompositionContainer _container;
protected override void Configure()
{
try
{
_container = new CompositionContainer(
new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x))));
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(_container);
StyleManager.ApplicationTheme = ThemeManager.FromName("Summer");
_container.Compose(batch);
}
catch (Exception exception)
{
}
}
public static void ReleaseAll()
{
}
protected override object GetInstance(Type serviceType, string key)
{
try
{
var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = _container.GetExportedValues<object>(contract);
if (exports.Any())
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
catch (ReflectionTypeLoadException ex)
{
foreach (Exception inner in ex.LoaderExceptions)
{
// write details of "inner", in particular inner.Message
}
return null;
}
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
try
{
return _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
catch (Exception exception)
{
return null;
}
}
protected override void BuildUp(object instance)
{
_container.SatisfyImportsOnce(instance);
}
}
ShellViewModel
[Export(typeof(ShellViewModel))]
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public ShellViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
Items.Add(compositionContainer.GetExportedValue<AViewModel>());
Items.Add(compositionContainer.GetExportedValue<BViewModel>());
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
public void B()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.B.ToString()));
}
public void A()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public void RESET()
{
AppBootstrapper.ReleaseAll();
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public enum AppMessageType
{
A,
B
}
}
AViewModel
[Export(typeof(AViewModel))]
public sealed class AViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public AViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.A.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
BViewModel
[Export(typeof(BViewModel))]
public sealed class BViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public BViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.B.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
Now AViewModel and BViewModel have single instance.
Whenever Release Button is clicked i want to have new instance of AViewModel and BViewModel.
Hoping to get a reply soon.
Regards,
Vivek
When working with an IoC container, the only part of your code that should take it as a dependency should be your composition root (i.e. your AppBootstrapper in this case). You shouldn't be injecting or referencing the container anywhere else in your code (except possibly factories).
If you want your ShellViewModel to control the lifetime of your child view models (A and B), then you should consider injecting view model factories into your ShellViewModel (via constructor injection if they are required dependencies).
Your AViewModelFactory would just have a single Create method that returns a new instance of AViewModel, likewise with the BViewModelFactory. You can simply new up your view models directly in the factories. If your view models have large dependency chains themselves, then you could consider adding a reference to your container in the factories, although preferably consider looking into the MEF ExportFactory<T> type.

Many operations with DataContext

I'm using EF for developing and enough new here.
I'm confused with how to work with EntityFramework context when I have to do different operations with context. Could you give me good tutorials and glance at my code for finding possible issues
Now I have next code
//domain.dll
class OrderDomainService
{
public void DoWork()
{
foreach(var order in GetOrders())
{
DeleteOrder(order);
}
}
public List<Order> GetOrders()
{
IOrderRepository orderRep = new OrderRepository();
return orderRep.GetAll();
}
public void DeleteOrder(Order order)
{
IOrderRepository orderRep = new OrderRepository();
return orderRep.Delete(order);
}
}
//repository.dll
public interface IOrderRepository
{
List<Order> GetAll();
void Delete(Order order);
void SaveContext()
}
public class OrderRepository
{
public OrderRepository()
{
if (ctx == null)
ctx = new EntityFrameworkDataContext();
}
static EntityFrameworkDataContext ctx { get; set; }
public List<Order> GetAll()
{
return ctx.Orders;
}
public void Delete(Order order)
{
ctx.Orders.Delete(order);
}
public void SaveContext()
{
ctx.SaveChanges();
ctx = null;
}
}
You need to share same EntityFrameworkDataContext instance between between several repositories (Use unit of work pattern http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx ).Because if you are doing an operaiton which you need to initiate two or more repositories you will have problems.