EFcore and dynamic model (iii). efcore Dynamic Model

Source: Internet
Author: User
Tags list of attributes

EFcore and dynamic model (iii). efcore Dynamic Model

Next to the above content, we will continue to look at the Implementation of Dynamic Model Page interaction, the content is as follows:

1. How to implement dynamic forms

2. How to receive and bind form data to a dynamic model

I. How to implement dynamic forms

Because the model information is customized in the background and is not a fixed structure, there is no way to directly write the corresponding form data on the page. Instead, you need to parse the structure of the model, dynamically generate the corresponding form. Before proceeding to the specific implementation method, let's take a look at what we want to achieve.

Html. Raw (FormGenerator. Generate (Model, Properties ))

FormGenerator. Generate contains two parameters: a dynamic model object and a list of attributes to be presented. The method returns the final generated form html, which is then presented to the page through Html. Raw.

The following describes the implementation process. First, define an IDynamicFormGenerator interface. The Code is as follows:

   public interface IDynamicFormGenerator    {        string Generate(object obj, IEnumerable<RuntimeModelMeta.ModelPropertyMeta> properties);    }

The Interface contains only one method, which is the method used by the above instance code. The interface implementation is logically simple. You only need to cycle every attribute, generate a form based on the characteristics of the attribute, and bind the object data to the form. For example, if the attribute is of the bool type, we can generate a checkbox, and then set the checkbox selection status based on whether the property value corresponding to obj is true or false. Specific implementation code:

Public class DynamicFormGenerator: IDynamicFormGenerator {public string Generate (object obj, IEnumerable <RuntimeModelMeta. modelPropertyMeta> properties) {StringBuilder builder = new StringBuilder (); // loop property set foreach (var item in properties) {// TODO: generate a form based on the attribute information and bind the data string fieldhtml = ""; // Add the generated html to the stringbulder builder. append (fieldhtml);} // return the final html result return builder. toString ();}}

The most important part of this method is how to generate the corresponding form based on the attribute type, and how to obtain the fieldhtml above? Let's take a look at the previously defined RuntimeModelMeta.

Public class RuntimeModelMeta {public int ModelId {get; set;} public string ModelName {get; set;} // model name public string ClassName {get; set ;} // class Name public string Properties {get; set;} // Attribute set json serialization result public class ModelPropertyMeta {public string Name {get; set ;} // The corresponding Chinese name public string PropertyName {get; set ;}// class property name public int Length {get; set ;}// Data Length, it is mainly used for string type public bool IsRequired {get; set ;}// whether the input is required. It is used for data verification public string ValueType {get; set ;}// data type, which can be a string, date, bool, etc }}

ModelPropertyMeta contains a ValueType information, which is the data type of the current attribute. can we determine the form based on this? The answer is no, because different forms are displayed even for the same type. For example, they are all strings. Some may require a drop-down box and some may require a check box. Therefore, it is not enough to rely only on ValueType, we can add an attribute to RuntimeModelMeta to set the form. The transformed code is as follows:

Public class RuntimeModelMeta {public int ModelId {get; set;} public string ModelName {get; set;} // model name public string ClassName {get; set ;} // class Name public string Properties {get; set;} // Attribute set json serialization result public class ModelPropertyMeta {public string Name {get; set ;} // The corresponding Chinese name public string PropertyName {get; set ;}// class property name public int Length {get; set ;}// Data Length, it is mainly used for string type public bool IsRequired {get; set ;}// whether the input is required. It is used for data verification public string ValueType {get; set ;}// data type, which can be a string, public string ShowType such as date and bool {get; set ;}// form }}

  

With ShowType, we can generate corresponding forms based on the set type. First, define a form Generator interface. The Code is as follows:

Public interface IDynamicFormFieldGenerator {// Generate the form string Generate (object obj, RuntimeModelMeta. modelPropertyMeta meta, bool onlyform = false); // This indicates the string ForType {get ;}} of the ShowType ;}}

Then we implement a generator for each ShowType. For example, for the ShowType of the checkbox type, we implement a generator. The Code is as follows:

Public class CheckboxFieldGenerator: IDynamicFormFieldGenerator {public string ForType {get {return "checkbox" ;}} public string Generate (object obj, RuntimeModelMeta. modelPropertyMeta meta, bool onlyform = false) {// converts a dynamic object to a DynamicEntity for later data retrieval convenience, because DynamicEntity supports retrieving attribute data through indexes DynamicEntity entity = obj as DynamicEntity; if (obj = null) {throw new NullReferenceException ("DynamicEntity ");} // Use entity [meta. propertyName] return string of the retrieved property data. format ("<input id = '{1}' name = '{1}' type = 'checkbox' value = '{0}'/>", entity [meta. propertyName]?. ToString (), meta. PropertyName );}}

  

Other ShowType types can be directly implemented based on the needs of your system. We will not list them here.

With the form constructor, let's go back and complete DynamicFormGenerator. In DynamicFormGenerator, we need to obtain IDynamicFormFieldGenerator Based on the ShowType information of the attribute. we can define a DynamicFormFieldGeneratorProvider, to help us get the IDynamicFormFieldGenerator we need, the specific implementation code:

// The provider interface defines public interface IDynamicFormFieldGeneratorProvider {IDynamicFormFieldGenerator Get (string type );}
Public class authorization: Allow {private readonly allow _ httpContextAccessor; private IEnumerable <strong> _ generators; public authorization (using httpContextAccessor) {_ httpContextAccessor = httpContextAccessor;} public authorization Get (string type) {// get the constructor implementation set through dependency injection, so we need to register all constructor implementations to ServiceCollection if (_ generators = null) {_ generators = _ httpContextAccessor. httpContext. requestServices. getServices <IDynamicFormFieldGenerator> ();} if (_ generators = null) {throw new NotSupportedException ("IDynamicFormFieldGenerator");} // locate the first qualified constructor based on type, and return IDynamicFormFieldGenerator g = _ generators. firstOrDefault (m => m. forType = type); if (g = null) {throw new NotSupportedException ("not supproted for" + type + "'s form field generator ");} return g ;}}

  

The conditions are ready and DynamicFormGenerator is directly improved. The final code is as follows:

Public class DynamicFormGenerator: extends {private readonly extends _ fieldGeneratorProvider; public DynamicFormGenerator (extends provider) {_ fieldGeneratorProvider = provider;} public string Generate (object obj, IEnumerable <RuntimeModelMeta. modelPropertyMeta> properties) {StringBuilder builder = new StringBuilder (); foreach (var item in properties) {// obtain the form constrtor IDynamicFormFieldGenerator fieldGenerator = _ fieldGeneratorProvider Based on showtype. get (item. showType); builder. append (fieldGenerator. generate (obj, item);} return builder. toString ();}}

  

The form can be displayed on the interface.

Ii. How to receive and bind form data to a dynamic model

The data binding mechanism is provided in mvc to quickly bind form data to objects. But now our objects are dynamic, how should we deal with them?

In form operations, we certainly know the corresponding model, so we can get a dynamic model object with the help of the content described above. The specific operations are as follows:

// Obtain type Type type modelType = _ runtimeModelProvider. GetType (modelid) based on the model id; // instantiate object obj = Activator. CreateInstance (modelType );

  

What we need to solve now is how to bind the data submitted by the dynamic form to the obj attribute. The method is also very simple. mvc provides us with good support. The method is TryUpdateModelAsync. With this method, you can easily bind data to obj and call the instance.

TryUpdateModelAsync (obj, modelType ,"")

Obj is the object instantiated above, and modelType is the Type information corresponding to the dynamic model. With the data, the Database Synchronization is completed through ef, such as adding

ShopDbContext.Add(obj);ShopDbContext.SaveChanges();

  

All codes must be supplemented by our own efforts. If there are any deficiencies, you are welcome to criticize and correct them.

  

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.