Subscribe to propertyChanged event PostSharp - mvvm

I have my ViewModel made with PostSharp:
[NotifyPropertyChanged]
class ProfileSelectorViewModel
{
public int Selection { get; set; }
}
Selection is bound to the selection property of a listbox. How can I subscribe to the change of this property? I want to call a method when Selection changes it's value.

You can subscribe to the PropertyChanged event by casting an object of ProfileSelectorViewModel class. Because your tooling may complain that the class does not implement the interface INotifyPropertyChanged yet, you can use a helper method Post.Cast<SourceType, TargetType>(SourceType).
So if you have an object obj of type ProfileSelectorViewModel and a method OnSelectionChanged handling the change, the subscription looks like this:
Post.Cast<ProfileSelectorViewModel,INotifyPropertyChanged>(obj).PropertyChanged += OnSelectionChanged;
See http://doc.postsharp.net/inotifypropertychanged-add#consuming for details.

Related

aspnetboilerplate EventCloud example - design pattern

in this tutorial about the EventCloud example app:
https://aspnetboilerplate.com/Pages/Documents/Articles/Developing-MultiTenant-SaaS-ASP.NET-CORE-Angular/index.html
the text states: the creation of a new entity must be done using the static method "Create" in the "Event" class (not using "new Entity(....)")
1) so my first question is: which design pattern is this? Factory? Builder? other?
[Table("AppEvents")]
public class Event : FullAuditedEntity<Guid>, IMustHaveTenant
{
......
....
...
/// <summary>
/// We don't make constructor public and forcing to create events using <see cref="Create"/> method.
/// But constructor can not be private since it's used by EntityFramework.
/// Thats why we did it protected.
/// </summary>
protected Event()
{
}
public static Event Create(int tenantId, string title, DateTime date, string description = null, int maxRegistrationCount = 0)
{
var #event = new Event
{
Id = Guid.NewGuid(),
TenantId = tenantId,
Title = title,
Description = description,
MaxRegistrationCount = maxRegistrationCount
};
#event.SetDate(date);
#event.Registrations = new Collection<EventRegistration>();
return #event;
}
....
...
2) the second question:
than the article says...
Event Manager .... All Event operations should be executed using this class... (EventManager)
ok, the CreateAsync method call the repository insert method, is the static "Event.Create" internaly called from the repository insert method? if yes, could you indicate me the point in the abp source code?
or is it an internal matter of EntityFramework?
public class EventManager : IEventManager
{
......
....
..
public async Task CreateAsync(Event #event)
{
await _eventRepository.InsertAsync(#event);
}
Here are my answers:
1-) Event is being created with a static factory method. There are 2 ways to create an entity in Domain Driven Design.
Creating with static factory methods: It's a convenient way of creating business entities. And this method is being used in EventCloud. The only downside of this method is it's static! If your entity is holding state it's not good for testability. But there are 3 advantages of this approach;
They have names: for example Event.CreatePublicEvent(), Create.PrivateEvent()
They can cache: You can cache them in a private static HashSet or Dictionary.
They can subtype.
Creating with a constructor: If you have only one constructor then creating an object through its public constructor is the most convenient approach in Domain Driven Design. As long as you make parameterless constructor protected or private. Besides, an entity should be responsible for its own data integrity and validity so you have to set all business related public properties as private setter and you should allow them to change through public methods.
Further information, see https://www.yegor256.com/2017/11/14/static-factory-methods.html
2-) EventManager is a domain service that is used for business logic. And Event.Create() is being used in the EventAppService class. Click here to see where exactly is being executed. Even Event.Create() method consists of a single line of code but it's open for extension.
I hope that will be useful ;)
Happy coding...

Why does [FromBody] ignore model binders?

I'm working on an REST API in ASP.NET. One of the first things I made was a Model Binder for the model, binded with the model by a code like this:
[ModelBinder(typeof(MyModelModelBinder))]
public class MyModel { ... }
And used it in an action
public IHttpActionResult Post(MyModel model) { ... }
I realised, quite suddenly, that after I added the [FromBody] before the parameter type...
public IHttpActionResult Post([FromBody]MyModel model) { ... }
...the Model Binder gets ignored. I tried to debug it by puting a breakpoint on the beginning of the BindModel method and at the beginning of the action and realised that when I call the action I get straight to the action. When I delete the FromBody Attribute the breakpoint in the ModelBinder becomes active again.
Why can't I use both? Why is the FromBody attribute ignoring the ModelBinder?

GWT Editor framework

Is there a way to get the proxy that editor is editing?
The normal workflow would be:
public class Class implments Editor<Proxy>{
#Path("")
#UiField AntoherClass subeditor;
void someMethod(){
Proxy proxy = request.create(Proxy.class);
driver.save(proxy);
driver.edit(proxy,request);
}
}
Now if i got a subeditor of the same proxy
public class AntoherClass implements Editor<Proxy>{
someMethod(){
// method to get the editing proxy ?
}
}
Yes i know i can just set the proxy to the Child editor with setProxy() after its creation, but i want to know if there is something like HasRequestContext but for the edited proxy.
This usefull when you use for example ListEditor in non UI objects.
Thank you.
Two ways you can get a reference to the object that a given editor is working on. First, some simple data and a simple editor:
public class MyModel {
//sub properties...
}
public class MyModelEditor implements Editor<MyModel> {
// subproperty editors...
}
First: Instead of implementing Editor, we can pick another interface that also extends Editor, but allows sub-editors (LeafValueEditor does not allow sub-editors). Lets try ValueAwareEditor:
public class MyModelEditor2 implements ValueAwareEditor<MyModel> {
// subproperty editors...
// ValueAwareEditor methods:
public void setValue(MyModel value) {
// This will be called automatically with the current value when
// driver.edit is called.
}
public void flush() {
// If you were going to make any changes, do them here, this is called
// when the driver flushes.
}
public void onPropertyChange(String... paths) {
// Probably not needed in your case, but allows for some notification
// when subproperties are changed - mostly used by RequestFactory so far.
}
public void setDelegate(EditorDelegate<MyModel> delegate) {
// grants access to the delegate, so the property change events can
// be requested, among other things. Probably not needed either.
}
}
This requires that you implement the various methods as in the example above, but the main one you are interested in will be setValue. You do not need to invoke these yourself, they will be called by the driver and its delegates. The flush method is also good to use if you plan to make changes to the object - making those changes before flush will mean that you are modifying the object outside of the expected driver lifecycle - not the end of the world, but might surprise you later.
Second: Use a SimpleEditor sub-editor:
public class MyModelEditor2 implements ValueAwareEditor<MyModel> {
// subproperty editors...
// one extra sub-property:
#Path("")//bound to the MyModel itself
SimpleEditor self = SimpleEditor.of();
//...
}
Using this, you can call self.getValue() to read out what the current value is.
Edit: Looking at the AnotherEditor you've implemented, it looks like you are starting to make something like the GWT class SimpleEditor, though you might want other sub-editors as well:
Now if i got a subeditor of the same proxy
public class AntoherClass implements Editor<Proxy>{
someMethod(){
// method to get the editing proxy ?
}
}
This sub-editor could implement ValueAwareEditor<Proxy> instead of Editor<Proxy>, and be guaranteed that its setValue method would be called with the Proxy instance when editing starts.
In your child editor class, you can just implement another interface TakesValue, you can get the editing proxy in the setValue method.
ValueAwareEditor works too, but has all those extra method you don't really need.
This is the only solution I found. It involves calling the context edit before you call the driver edit. Then you have the proxy to manipulate later.

MEF and IObservables

I have a singleton IObservable that returns the results of a Linq query. I have another class that listens to the IObservable to structure a message. That class is Exported through MEF, and I can import it and get asynchronous results from the Linq query.
My problem is that after initial composition takes place, I don't get any renotification on changes when the data supplied to the Linq query changes. I implemented INotifyPropertyChanged on the singleton, thinking it word make the exported class requery for a new IObservable, but this doesn't happen.
Maybe I'm not understanding something about the lifetime of MEF containers, or about property notification. I'd appreciate any help.
Below are the singleton and the exported class. I've left out some pieces of code that can be inferred, like the PropertyChanged event handlers and such. Suffice to say, that does work when the underlying Session data changes. The singleton raises a change event for UsersInCurrentSystem, but there is never any request for a new IObservable from the UsersInCurrentSystem property.
public class SingletonObserver: INotifyPropertyChanged
{
private static readonly SingletonObserver _instance = new SingletonObserver();
static SingletonObserver() { }
private SingletonObserver()
{
Session.ObserveProperty(xx => xx.CurrentSystem, true)
.Subscribe(x =>
{
this.RaisePropertyChanged(() => this.UsersInCurrentSystem);
});
}
public static SingletonObserverInstance { get { return _instance; } }
public IObservable<User> UsersInCurrentSystem
{
get
{
var x = from user in Session.CurrentSystem.Users
select user;
return x.ToObservable();
}
}
}
[Export]
public class UserStatus : INotifyPropertyChanged
{
private string _data = string.Empty;
public UserStatus
{
SingletonObserver.Instance.UsersInCurrentSystem.Subscribe(sender =>
{
//set _data according to information in sender
//raise PropertyChanged for Data
}
}
public string Data
{
get { return _data; } }
}
}
My problem is that after initial composition takes place, I don't get any renotification on changes when the data supplied to the Linq query changes.
By default MEF will only compose parts once. When a part has been composed, the same instance will be supplied to all imports. The part will not be recreated unless you explicitly do so.
In your case, if the data of a part change, even if it implements INotifyPropertyChanged, MEF will not create a new one, and you don't need to anyway.
I implemented INotifyPropertyChanged on the singleton, thinking it word make the exported class requery for a new IObservable
No.
Maybe I'm not understanding something about the lifetime of MEF containers, or about property notification.
Property notification allows you to react to a change in the property and has no direct effect on MEF. As for the container's lifetime, it will remain active until it is disposed. While it is still active, the container will keep references to it's compose parts. It's actually a little more complex than that, as parts can have different CreationPolicy that affects how MEF holds the part, I refer you to the following page: Parts Lifetime for more information.
MEF does allow for something called Recomposition. You can set it likewise:
[Import(AllowRecomposition=true)]
What this does tough is allow MEF to recompose parts when new parts are available or existing parts aren't available anymore. From what I understand it isn't what you are referring to in your question.

MVVM and Repository Question

Let's say that I have two views in my app, MemberListView and MemberEditView. They are associated with their perspective viewModels, MemberListViewModel and MemberEditViewModel. The models speak to a repository class, MemberRepository, which has the CRUD methods for the member class.
In the MemberEditView form, I have several dropdowns that display thinkgs like Status (Active/Inactive/Pending), the members trade code etc. They are ObservableCollection objects in my viewModel and are bound to ComboBoxes on the view. Should the MemberRepository handle the gets for retrieving the lists of each to be displayed?
What if on the MemberEditView I have a grid that displays all the jobs that the member has had over the years. If the user doubleclicks one of the jobs, it calls a JobHistoryEditView to display the job Information and it has a JobHistoryViewModel. Should the MemberRepository take care of the JobHistory CRUD methods or should I have a separate JobHistory Repository?
Most MVVM applications would have this architecture:
View -> ViewModel -> Model -> Repository
I have recently been espousing a variant:
View -> ViewModel <- Presenter -> Model -> Repository
(Where A -> B means "A knows about B", but B doesn't know about A.)
Notice that in both cases, the only thing that knows about the repository is the Model, not the ViewModel. Your model isn't just the domain entities, it also has to house the business logic. Obviously one of the user stories your business logic has to support is something I'll call a MemberEditTask:
public class MemberEditTask
{
private readonly Member _member;
public MemberEditTask(Member member, IRepository repository)
{
this._member = member;
this.StatusChoices = repository.GetPossibleMemberStatuses(member);
}
public ReadOnlyCollection<MemberStatus> StatusChoices { get; private set; }
public MemberStatus Status
{
get { return this._member.Status; }
set
{
if(!this.StatusChoices.Contains(value))
{
throw new ArgumentOutOfRangeException();
}
this._member.Status = value;
}
}
}
All of this logic belongs in your Model because the list of possible choices (and validating that one of those was actually chosen) is defined by business logic. You could also imagine some other thing consuming the MemberEditTask, like an automated process running on the server that edits a member in response to a file uploaded on an FTP server, or a background process (setting the status to Inactive after a certain amount of time). All of those things need to execute the same business rules, so it all has to be common (not in the ViewModel).
So given that class, the ViewModel class looks like this:
public class MemberEditViewModel : ViewModelBase
{
private readonly MemberEditTask _task;
public MemberEditViewModel(MemberEditTask task)
{
this._task = task;
}
public IEnumerable<MemberStatus> StatusChoices
{ get { return this._task.StatusChoices; }
public MemberStatus Status
{
get { return this._task.Status; }
set
{
this._task.Status = value;
NotifyAllPropertiesChanged();
}
}
}
In this case, as a very simple convenience, just believe that NotifyAllPropertiesChanged is a protected method of ViewModelBase that uses reflection to raise a PropertyChanged event on all public properties of the ViewModel. :) That's overkill of course, but it drives at a more important point...
This is almost a silly example because in this case, MemberEditViewModel is unnecessary. If the View is the only one setting Status then there's really no need to raise the property changed event either! Of course in the real world, you will have more properties and there will be interactions. The reason for the ViewModel to exist is to notify consumers when its view-related properties change, which is something the Model doesn't do (and shouldn't in my opinion). (The ViewModel also has extra View-specific logic to support animations, etc.)
So back to your question... whether or not the MemberRepository is responsible for executing the gets of the statuses is irrelevant from the point of view of the ViewModel because the repository is a service used by the Model. The Model is a service used by the ViewModel. Make your Model of the task/workflow/process/whatever expose the list of status options.
Sorry if that was long-winded.