This document cannot be reproduced or referenced without the permission of the author. to reference this document, contact the author by email. Contact the email address xuanzhaopeng # gmail.com.
During the development of windows desktop applications or windows phone apps, we will use WPF. NET, and its highlight is that the interface design and software logic are completely separated, all data is bound, and all commands are also bound, here, we will not describe how to bind variables and commands in redundancy. After binding data, we will focus on the design of data in the backend logic through dependency injection. The reason for this is that, the data used by our app may come from webservice, for example, mobile app. We cannot store a large database on our mobile phone. Instead, we use webservice to retrieve and update data. Therefore, if we still actively monitor the data, this means that the data update is passive and must be triggered by the user. After the trigger, the obtained data is set to the variable bound to the page, how do you implement a real-time system? Only dependency injection can be used, and dependency injection can make your system more modular. So let me give you an example.
We now have a ViewModel to initialize.
[Csharp] [AppViewModel]
Class ClockViewModel
{
Public ClockViewModel (IServices Services)
{
}
}
[AppViewModel]
Class ClockViewModel
{
Public ClockViewModel (IServices Services)
{
}
}
This viewmodel is stored in a dll. Now we need to dynamically load this class. At this time, we must use the Assembly and Attribute
[Csharp] private Type GetClassByAttribute (Type attributeType)
{
Assembly assembly = this. GetType (). Assembly;
Var types = assembly. GetTypes (). Where (t => Attribute. IsDefined (t, attributeType). ToList ();
Return types. First ();
}
Private Type GetClassByAttribute (Type attributeType)
{
Assembly assembly = this. GetType (). Assembly;
Var types = assembly. GetTypes (). Where (t => Attribute. IsDefined (t, attributeType). ToList ();
Return types. First ();
}
Through the GetClassByAttribute function, the input parameter is of the AppViewModel Type, and we can get the Type of ClockViewModel.
Now we need to register this Type in dependency injection.
[Csharp] ype ViewModelType = this. GetClassByAttribute (typeof (AppViewModelAttribute ));
This. IoCContainer. RegisterType (ViewModelType );
Type ViewModelType = this. GetClassByAttribute (typeof (AppViewModelAttribute ));
This. IoCContainer. RegisterType (ViewModelType );
;
At this point, we only get the ViewModel type through Assembly, instead of the instantiated object. The current goal is to initialize this instance object.
Therefore, we need to use the following method to obtain the instantiated object
[Csharp] this. ViewModel = this. IoCContainer. Resolve (ViewModelType );
This. ViewModel = this. IoCContainer. Resolve (ViewModelType );
As a result, we can use the Resolve Method to pass in the type to obtain this object. Now, review all the previous steps, and there is basically no redundancy in the layer-by-layer instantiation!
But !!! It is not over yet. Some may ask, in the ViewModel constructor, an object whose parameter type is IService must be input, but we have never processed this object, therefore, you must initialize these interface objects before executing the last line of code !!
[Csharp] this. IoCContainer. RegisterType <IDataStreamingChannelFactory, DataStreamingChannelFactory> ();
This. IoCContainer. RegisterType <IStreamingDataProvider, StreamingDataProvider> ();
This. IoCContainer. RegisterType <IServices, ServiceRoot> ();
This. IoCContainer. RegisterType <IDataStreamingChannelFactory, DataStreamingChannelFactory> ();
This. IoCContainer. RegisterType <IStreamingDataProvider, StreamingDataProvider> ();
This. IoCContainer. RegisterType <IServices, ServiceRoot> ();
Let's take a look at the ServiceRoot constructor,
[Csharp] internal class ServiceRoot: IServices, IDataServices, IInfraServices
{
Public ServiceRoot (IIoCContainer ioc, IDataStreamingChannelFactory channelFactory, IStreamingDataProvider streamingProvider)
{
}
}
Internal class ServiceRoot: IServices, IDataServices, IInfraServices
{
Public ServiceRoot (IIoCContainer ioc, IDataStreamingChannelFactory channelFactory, IStreamingDataProvider streamingProvider)
{
}
}
IDataStreamingChannelFactory and IStreamingDataProvider are used in the constructor. Therefore, we should register both of them before registering IService.
By now, all the steps are completed, and a zero-Coupling Object Instantiation process is completed.