临小时搞精晓表明处理器,MVC开发基础学习笔记

 

一、2个效能强大的页面开发帮忙类—HtmlHelper开始精通

HTML扩大类的全部办法都有3个参数:
以textbox为例子
public static string TextBox( this HtmlHelper htmlHelper, string name,
Object value, IDictionary<string, Object> htmlAttributes )
public static string TextBox( this HtmlHelper htmlHelper, string name,
Object value, Object htmlAttributes )
那1个参数代表这么些html标签的属性集合。使用方法如下。
 
1.ActionLink
<%=Html.ActionLink(“那是1个接连”, “Index”, “Home”)%>
带有QueryString的写法
<%=Html.ActionLink(“那是二个老是”, “Index”, “Home”, new { page=1},null)%>
<%=Html.ActionLink(“那是一个总是”, “Index”, new { page=一 })%>
有其余Html属性的写法
<%=Html.ActionLink(“那是三个连接”, “Index”, “Home”, new { id=”link1″
})%>
<%=Html.ActionLink(“那是三个连连”, “Index”,null, new { id=”link一”
})%>
QueryString与Html属性同时存在
<%=Html.ActionLink(“这是一个连连”, “Index”, “Home”, new { page = 一 },
new { id = “link一” })%>
<%=Html.ActionLink(“那是一个连连”, “Index” , new { page = 1 }, new {
id = “link一” })%>
 
变动结果为:
<a href=”/”>那是2个总是</a>
带有QueryString的写法
<a href=”/?page=1″>这是三个接连</a>
<a href=”/?page=1″>那是三个总是</a>
有任何Html属性的写法
<a href=”/?Length=肆” id=”link1″>这是2个总是</a>
<a href=”/” id=”link一”>那是叁个连接</a>
QueryString与Html属性同时存在
<a href=”/?page=①” id=”link①”>那是三个连接</a>
<a href=”/?page=1″ id=”link一”>那是2个三番五次</a>
 
2.RouteLink
临小时搞精晓表明处理器,MVC开发基础学习笔记。跟ActionLink在功效上1致。
<%=Html.RouteLink(“关于”, “about”, new { })%>
带QueryString
<%=Html.RouteLink(“关于”, “about”, new { page = 1 })%>
<%=Html.RouteLink(“关于”, “about”, new { page = 1 }, new { id =
“link1” })%>
 
变化结果:
<a href=”/about”>关于</a>
<a href=”/about?page=1″>关于</a>
<a href=”/about?page=1″ id=”link1″>关于</a>
3.Form   2种方法
<%using(Html.BeginForm(“index”,”home”,FormMethod.Post)){%>
<%} %>
 
<%Html.BeginForm(“index”, “home”,
FormMethod.Post);//注意那里未有=输出%>
<%Html.EndForm(); %>
 
扭转结果:
<form action=”/home/index” method=”post”></form>
4.TextBox
, Hidden ,
<%=Html.TextBox(“input1”) %>
<%=Html.TextBox(“input2”,Model.CategoryName,new{ @style =
“width:300px;” }) %>
亚洲必赢官网 ,<%=Html.TextBox(“input3”, ViewData[“Name”],new{ @style =
“width:300px;” }) %>
<%=Html.TextBoxFor(a => a.CategoryName, new { @style =
“width:300px;” })%>
 
变化结果:
 
<input id=”input1″ name=”input1″ type=”text” value=”” />
<input id=”input2″ name=”input2″ style=”width:300px;” type=”text”
value=”Beverages” />
<input id=”input3″ name=”input3″ style=”width:300px;” type=”text”
value=”” />
<input id=”CategoryName” name=”CategoryName” style=”width:300px;”
type=”text” value=”Beverages” />
 
5.TextArea
<%=Html.TextArea(“input5”, Model.CategoryName, 3, 9,null)%>
<%=Html.TextAreaFor(a => a.CategoryName, 3, 3, null)%>
 
转变结果:
<textarea cols=”9″ id=”input5″ name=”input5″
rows=”3″>Beverages</textarea>
<textarea cols=”3″ id=”CategoryName” name=”CategoryName”
rows=”3″>Beverages</textarea>
 
6.CheckBox
<%=Html.CheckBox(“chk1”,true) %>
<%=Html.CheckBox(“chk1″, new { @class=”checkBox”}) %>
<%=Html.CheckBoxFor(a =>a.IsVaild, new { @class = “checkBox”
})%>
 
浮动结果:
 
<input checked=”checked” id=”chk1″ name=”chk1″ type=”checkbox”
value=”true” /><input name=”chk1″ type=”hidden” value=”false”
/>
 
<input class=”checkBox” id=”chk1″ name=”chk1″ type=”checkbox”
value=”true” /><input name=”chk1″ type=”hidden” value=”false”
/>
 
<input checked=”checked” class=”checkBox” id=”IsVaild” name=”IsVaild”
type=”checkbox” value=”true” /><input name=”IsVaild” type=”hidden”
value=”false” />
 
7.ListBox
<%=Html.ListBox(“lstBox1”,(SelectList)ViewData[“Categories”])%>
<%=Html.ListBoxFor(a => a.CategoryName,
(SelectList)ViewData[“Categories”])%>
 
变更结果:
<select id=”lstBox1″ multiple=”multiple” name=”lstBox1″>
<option value=”1″>Beverages</option>
<option value=”2″>Condiments</option>
<option selected=”selected” value=”3″>Confections</option>
<option value=”4″>Dairy Products</option>
<option value=”5″>Grains/Cereals</option>
<option value=”6″>Meat/Poultry</option>
<option value=”7″>Produce</option>
<option value=”8″>Seafood</option>
</select>
<select id=”CategoryName” multiple=”multiple”
name=”CategoryName”>
<option value=”1″>Beverages</option>
<option value=”2″>Condiments</option>
<option value=”3″>Confections</option>
<option value=”4″>Dairy Products</option>
<option value=”5″>Grains/Cereals</option>
<option value=”6″>Meat/Poultry</option>
<option value=”7″>Produce</option>
<option value=”8″>Seafood</option>
</select>
 
8.DropDownList
<%= Html.DropDownList(“ddl1”,
(SelectList)ViewData[“Categories”],  “–Select One–“)%>
<%=Html.DropDownListFor(a => a.CategoryName,
(SelectList)ViewData[“Categories”], “–Select One–“, new { @class =
“dropdownlist” })%>
 
扭转结果:
<select id=”ddl1″ name=”ddl1″>
<option value=””>–Select One–</option>
<option value=”1″>Beverages</option>
<option value=”2″>Condiments</option>
<option selected=”selected” value=”3″>Confections</option>
<option value=”4″>Dairy Products</option>
<option value=”5″>Grains/Cereals</option>
<option value=”6″>Meat/Poultry</option>
<option value=”7″>Produce</option>
<option value=”8″>Seafood</option>
</select>
<select class=”dropdownlist” id=”CategoryName”
name=”CategoryName”>
<option value=””>–Select One–</option>
<option value=”1″>Beverages</option>
<option value=”2″>Condiments</option>
<option value=”3″>Confections</option>
<option value=”4″>Dairy Products</option>
<option value=”5″>Grains/Cereals</option>
<option value=”6″>Meat/Poultry</option>
<option value=”7″>Produce</option>
<option value=”8″>Seafood</option>
</select>
 
玖.Partial
视图模板
webform里叫自定义控件。成效都以为了复用。但运用上自定义控件真的很难用好。
<% Html.RenderPartial(“DinnerForm”);
%>  看通晓了并没有等号的。

Java中的评释是个很神奇的东西,还不打听的能够看下1钟头搞精通自定义评释(Annotation)。今后无数Android的库都用利用注脚达成的,比如ButterKnife,大家不防也来读书一下,学完注脚处理器,我们品尝写三个简单易行的好像ButterKnife的东西来绑定控件。

群里一小伙伴在开发应用程式时遇上了难点,便截图提问

一.1 有失必有得

亚洲必赢官网 1

  在ASP.Net
MVC中微软并未提供类似服务器端控件那种开发方式,终归微软的MVC就是古板的伸手处理响应的回归。所以吐弃此前的那种事件响应的模子,扬弃服务器端控件也理所当然。

  但是,假诺手写Html标签成效又比较低,可重耗费比较低。那时,咱们该怎么样来提升功效呢?首先,经过上篇大家通晓可以透过ViewData传递数据,于是大家得以写出以下的Html代码:

<input name="UserName" type="text" value="<%: ViewData["UserName"] %>" />

  尽管上述代码能够缓解难题,不过功能照旧相比低,尤其是在列表集合项较多的时候,工作量会相比较大。那么,还有木有一种更加好的不二秘诀呢?别急,微软早已为我们想好了国策。微软为开发职员飞快支付前台页面提供了累加的HtmlHelper的鼎力相助类,协理我们连忙支付前台页面,也提供了可扩张的接口,前台页面包车型客车标签能够能够成功中度可选用

怎样是注明处理器?

表明处理器是(Annotation Processor)是javac的1个工具,用来在编译时环顾和编写翻译和处理注明(Annotation)。你能够团结定义评释和注释处理器去搞一些政工。叁个申明处理器它以Java代码或许(编写翻译过的字节码)作为输入,生成文书(平常是java文件)。那么些生成的java文件不可能修改,并且会同其手动编写的java代码壹样会被javac编写翻译。看到那里丰裕以前知道,应该清楚大致的长河了,正是把标记了诠释的类,变量等作为输入内容,经过评释处理器处理,生成想要生成的java代码。

亚洲必赢官网 2

1.2 HtmlHelper初窥

  大家能够经过在页面中经过Html.XXX来促成快速的Html标签编辑,并且能够便宜地开始展览数据绑定。

<%: Html.Raw("<p>Hello,I am HtmlHelper!</p>") %>

  那么,为啥能够在页面中调用Html.XXX方法呢?通过ILSpy反编写翻译ViewPage页,大家得以见见原来在ViewPage下有二个HtmlHelper类型的属性-Html。(这下终于驾驭,为啥可以在页面中应用Html.xxxx()了)

亚洲必赢官网 3

  那么那一个HtmlHelper类又是二个怎么品种的大神啊?继续反编写翻译查看,在System.Web.Mvc命名空间下的HtmlHelper类型如下图所示,经过MSDN大神的上书,HtmlHelper扶助在视图中呈现HTML
控件。那大家看看在此类中有木有旧事中的TextBox、CheckBox的章程吗?经查看,木有。

亚洲必赢官网 4

  那么,我们为什么能够在页面中动用Html.TextBox()方法吧?那里就事关到八个誉为“扩充方法”的东东了,HtmlHelper 类的扩展方法在 System.Web.Mvc.Html
命名空间中。 那一个扩大添加了用于成立窗体、显示 HTML
控件、展现分部视图、执行输入验证等作用的扶助器方法。那么,有关如何自定义扩大方法请参阅本文第一有的,那里先卖个点子,暂不介绍。

亚洲必赢官网 5

处理器AbstractProcessor

处理器的写法有定位的老路,继承AbsstractProcessor。如下:

public class MyProcessor extends AbstractProcessor {
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv){
        super.init(processingEnv);
    }
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return null;
    }
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        return true;
    }
}
  • init(ProcessingEnvironment processingEnv)
    被诠释处理工科具调用,参数ProcessingEnvironment
    提供了Element,Filer,Messager等工具
  • getSupportedAnnotationTypes()
    钦赐表明处理器是登记给这几个诠释的,它是二个字符串的聚众,意味着可以支撑多个体系的注释,并且字符串是合法全名。
  • getSupportedSourceVersion 指定Java版本
  • process(Set<? extends TypeElement> annotations,
    RoundEnvironment roundEnv)
    那些也是最重视的,在此间扫描和处理你的注释并生成Java代码,音信都在参数RoundEnvironment
    里了,前面会介绍。

在Java七 中还能运用

@SupportedSourceVersion(SourceVersion.latestSupported())
@SupportedAnnotationTypes({
   // 合法注解全名的集合
 })

取而代之 getSupportedSourceVersion() 和 getSupportedAnnotationType()
,没毛病,还是可以够在诠释处理离器中应用注脚。

1、傻瓜式消除办法:

一.三 为什么选择HtmlHelper?

   考虑这样1个风貌:大家的品种第3个本子中的路由规则是那般的{controller}/{action}/{id},于是大家项目中颇具的<a>标签所针对的都以以刚刚的条条框框命名的href(例如:<a
></a>)。然而在其次版中,我们的路由规则也会化为了{controller}-{action}-{id},那么大家恰好为超链接所设置的href便都不能够平常访问了。那时,我们必要展开交换,单个替换或批量交替(例如改为:<a
></a>),固然也足以缓解难题,不过的确增添了工作量,功用相当低。

  那么,怎么样来遮掩这种转移所带来的困顿呢?那里,通过动用HtmlHelper为大家提供的ActionLink标签,便得以消除这些难题。因为HtmlHelper是从服务器端自动帮您生成a标签,由此所生成的href会遵守如今的路由规则,也就帮大家遮挡了变动,升高了工效。

登记申明处理器

包装声明处理器的时候要求三个特出的文本
javax.annotation.processing.Processor 在 META-INF/services 路径下

--myprcessor.jar
----com
------example
--------MyProcessor.class
----META-INF
------services
--------javax.annotation.processing.Processor

包裹进javax.annotation.processing.Processor的内容是电脑的法定全称,八个总括机之间换行。

com.example.myprocess.MyProcessorA
com.example.myprocess.MyProcessorB

google提供了2个注册处理器的库

compile 'com.google.auto.service:auto-service:1.0-rc2'

一个证明消除:

@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {
      ...
}

读到那里ButterKnife用到的知识点大家都早已精晓了
壹.自定义注脚
二.用申明处理器解析注明
3.解析完毕后生成Java文件
BufferKnife使用:

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.rxjava_demo)
    Button mRxJavaDemo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mRxJavaDemo.setText("Text");
    }

}

然后大家编写翻译一下,打开路径:/app/build/intermediates/classes/release/com/ming/rxdemo/MainActivity$$ViewBinder.class
那正是大家转移的Java文件,能够见见Button已经在bind里面早先化了。

public class MainActivity$$ViewBinder<T extends MainActivity> implements ViewBinder<T> {
    public MainActivity$$ViewBinder() {
    }

    public void bind(Finder finder, T target, Object source) {
        View view = (View)finder.findRequiredView(source, 2131492944, "field \'mRxJavaDemo\'");
        target.mRxJavaDemo = (Button)finder.castView(view, 2131492944, "field \'mRxJavaDemo\'");
    }

    public void unbind(T target) {
        target.mRxJavaDemo = null;
    }
}

接下去大家制造3个档次,写1个简短的用申明绑定控件的事例

  删除:

2、没有服务器控件也能干大事—HtmlHelper首要方法介绍

  PS:那里的实例均未有加<% %>或@符号,要运行请自行加上。

  (1)ActionLink与RouteLink

Html.ActionLink("这是一个连接", "Index", "Home")  带有QueryString的写法  Html.ActionLink("这是一个连接", "Index", "Home", new { page=1 },null)  Html.ActionLink("这是一个连接", "Index", new { page=1 })  有其它Html属性的写法  Html.ActionLink("这是一个连接", "Index", "Home", new { id="link1" })  Html.ActionLink("这是一个连接", "Index",null, new { id="link1" })  QueryString与Html属性同时存在  Html.ActionLink("这是一个连接", "Index", "Home", new { page = 1 }, new { id = "link1" })  Html.ActionLink("这是一个连接", "Index" , new { page = 1 }, new { id = "link1" })

  其生成的结果为:

<a href="/">这是一个连接</a>  带有QueryString的写法  <a href="/?page=1">这是一个连接</a>  <a href="/?page=1">这是一个连接</a>  有其它Html属性的写法  <a href="/?Length=4" id="link1">这是一个连接</a>  <a href="/" id="link1">这是一个连接</a>  QueryString与Html属性同时存在  <a href="/?page=1" id="link1">这是一个连接</a>  <a href="/?page=1" id="link1">这是一个连接</a>

  RouteLink在用法大约与ActionLink1致,那里就不再介绍,详情请出席MSDN;

  (2)TextBox与TextArea

  ①TextBox

Html.TextBox("input1")   Html.TextBox("input2",Model.CategoryName,new{ @style = "width:300px;" })   Html.TextBox("input3", ViewData["Name"],new{ @style = "width:300px;" })   Html.TextBoxFor(a => a.CategoryName, new { @style = "width:300px;" })

  其变动的结果为:

<input id="input1" name="input1" type="text" value="" />  <input id="input2" name="input2" style="width:300px;" type="text" value="Beverages" />  <input id="input3" name="input3" style="width:300px;" type="text" value="" />  <input id="CategoryName" name="CategoryName" style="width:300px;" type="text" value="Electronic" />

  ②TextArea

Html.TextArea("input5", Model.CategoryName, 3, 9,null)  Html.TextAreaFor(a => a.CategoryName, 3, 3, null)

  其转移的结果为:

<textarea cols="9" id="input5" name="input5" rows="3">Electronic</textarea>  <textarea cols="3" id="CategoryName" name="CategoryName" rows="3">Electronic</textarea>

  那里可以见见,我们得以使用强类型来生成Html标签,例如:Html.TextBoxFor(a
=> a.CategoryName, new { @style = “width:300px;”
}),这里的CategoryName便是有些项目标性质。

  (3)CheckBox

Html.CheckBox("chk1",true)   Html.CheckBox("chk1", new { @class="checkBox"})   Html.CheckBoxFor(a =>a.IsVaild, new { @class = "checkBox" })

   其生成的结果为:

<input checked="checked" id="chk1" name="chk1" type="checkbox" value="true" /><input name="chk1" type="hidden" value="false" />  <input class="checkBox" id="chk1" name="chk1" type="checkbox" value="true" /><input name="chk1" type="hidden" value="false" />  <input checked="checked" class="checkBox" id="IsVaild" name="IsVaild" type="checkbox" value="true" /><input name="IsVaild" type="hidden" value="false" />

  (4)DropDownList

Html.DropDownList("ddl1", (SelectList)ViewData["Categories"],  "--Select One--")  Html.DropDownListFor(a => a.CategoryName, (SelectList)ViewData["Categories"], "--Select One--", new { @class = "dropdownlist" })

  其转移的结果为:

<select id="ddl1" name="ddl1">  <option value="">--Select One--</option>  <option value="1">Beverages</option>  <option value="2">Condiments</option>  <option selected="selected" value="3">Confections</option>  <option value="4">Dairy Products</option>  <option value="5">Grains/Cereals</option>  <option value="6">Meat/Poultry</option>  <option value="7">Produce</option>  <option value="8">Seafood</option>  </select>  <select class="dropdownlist" id="CategoryName" name="CategoryName">  <option value="">--Select One--</option>  <option value="1">Beverages</option>  <option value="2">Condiments</option>  <option value="3">Confections</option>  <option value="4">Dairy Products</option>  <option value="5">Grains/Cereals</option>  <option value="6">Meat/Poultry</option>  <option value="7">Produce</option>  <option value="8">Seafood</option>  </select>

  (5)RadioButton

男<%: Html.RadioButton("Gender","1",true) %>  女<%: Html.RadioButton("Gender","2",false) %>

  其变化的代码为:

男<input checked="checked" id="Gender" name="Gender" type="radio" value="1" />  女<input id="Gender" name="Gender" type="radio" value="2" />

  (6)Encode与Raw

  Encode会将内容实行编码话,因而,如若你的剧情中包罗Html标签的话那么会被解析成特殊字符,例如:

<%: Html.Encode("<p>哈哈</p>") %>

  其生成的代码为:

&amp;lt;p&amp;gt;哈哈&amp;lt;/p&amp;gt;

  那里首若是为了防范XSS攻击和恶意脚本,因而在MVC中,默许的<%:
%>就落到实处了<%: Html.Encode()
%>。可是,有些时候假诺大家需求输出Html或JavaScript内容的字符串,那时大家得以动用HtmlHelper为我们提供的别的办法。例如大家要出口刚刚那句话,大家能够如下使用:

<%: Html.Raw("<p>哈哈</p>") %>

  其生成的代码为:

<p>哈哈</p>

  在HtmlHelper中还提供了好多的扩张方法供大家有利成立Html,比如:BeginForm、EndForm等。关于任何的诀窍介绍,请自行检索,那里不再一1赘述。

项目结构

--apt-demo
----bindview-annotation(Java Library)
----bindview-api(Android Library)
----bindview-compiler(Java Library)
----app(Android App)
  • bindview-annotation 评释申明
  • bindview-api 调用Android SDK API
  • bindview-compiler 注明处理器相关
  • app 测试App

一.在 bindview-annotation
下创立2个@BindView表明,该证明重返三个值,整型,名称叫value,用来代表控件ID。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface BindView {
    /**
     * 用来装id
     *
     * @return
     */
    int value();
}

二.在 bindview-compiler 中开创表明处理器 BindViewProcessor
并登记,做为主的开头化学工业作。

@AutoService(Processor.class)
public class BindViewProcessor extends AbstractProcessor {
    /**
     * 文件相关的辅助类
     */
    private Filer mFiler;
    /**
     * 元素相关的辅助类
     */
    private Elements mElementUtils;
    /**
     * 日志相关的辅助类
     */
    private Messager mMessager;
    /**
     * 解析的目标注解集合
     */
    private Map<String, AnnotatedClass> mAnnotatedClassMap = new HashMap<>();

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        mElementUtils = processingEnv.getElementUtils();
        mMessager = processingEnv.getMessager();
        mFiler = processingEnv.getFiler();
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new LinkedHashSet<>();
        types.add(BindView.class.getCanonicalName());//返回该注解处理器支持的注解集合
        return types;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        return true;
    }
}

是或不是小心到了内部有个Map容器,而且类型是AnnotatedClass,那是干啥的吗?这几个很好驾驭,大家在解析XML,解析Json的时候数据解析完未来是或不是要以对象的花样表示出来,那里也同等,@BindView用来标记类成员,多个类下能够有多少个成员,好比1个Activity中得以有多少个控件,三个容器下有多个控件等。如下:

package com.mingwei.myprocess.model;

import com.mingwei.myprocess.TypeUtil;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import java.util.ArrayList;
import java.util.List;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;

/**
 * Created by mingwei on 12/10/16.
 * CSDN:    http://blog.csdn.net/u013045971
 * Github:  https://github.com/gumingwei
 */
public class AnnotatedClass {
    /**
     * 类名
     */
    public TypeElement mClassElement;
    /**
     * 成员变量集合
     */
    public List<BindViewField> mFiled;
    /**
     * 元素辅助类
     */
    public Elements mElementUtils;

    public AnnotatedClass(TypeElement classElement, Elements elementUtils) {
        this.mClassElement = classElement;
        this.mElementUtils = elementUtils;
        this.mFiled = new ArrayList<>();
    }
    /**
     * 获取当前这个类的全名
     */
    public String getFullClassName() {
        return mClassElement.getQualifiedName().toString();
    }
    /**
     * 添加一个成员
     */
    public void addField(BindViewField field) {
        mFiled.add(field);
    }
    /**
     * 输出Java
     */
    public JavaFile generateFinder() {
        return null;
    }
    /**
     * 包名
     */
    public String getPackageName(TypeElement type) {
        return mElementUtils.getPackageOf(type).getQualifiedName().toString();
    }
    /**
     * 类名
     */
    private static String getClassName(TypeElement type, String packageName) {
        int packageLen = packageName.length() + 1;
        return type.getQualifiedName().toString().substring(packageLen).replace('.', '$');
    }
}

成员用BindViewField表示,没什么复杂的逻辑,在构造函数判断项目和初阶化,简单的get函数

package com.mingwei.myprocess.model;

import com.mingwe.myanno.BindView;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Name;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

/**
 * Created by mingwei on 12/10/16.
 * CSDN:    http://blog.csdn.net/u013045971
 * Github:  https://github.com/gumingwei
 * 被BindView注解标记的字段的模型类
 */
public class BindViewField {

    private VariableElement mFieldElement;

    private int mResId;

    public BindViewField(Element element) throws IllegalArgumentException {
        if (element.getKind() != ElementKind.FIELD) {//判断是否是类成员
            throw new IllegalArgumentException(String.format("Only field can be annotated with @%s",
                    BindView.class.getSimpleName()));
        }
        mFieldElement = (VariableElement) element;
        //获取注解和值
        BindView bindView = mFieldElement.getAnnotation(BindView.class);
        mResId = bindView.value();
        if (mResId < 0) {
            throw new IllegalArgumentException(String.format("value() in %s for field % is not valid",
                    BindView.class.getSimpleName(), mFieldElement.getSimpleName()));
        }
    }

    public Name getFieldName() {
        return mFieldElement.getSimpleName();
    }

    public int getResId() {
        return mResId;
    }

    public TypeMirror getFieldType() {
        return mFieldElement.asType();
    }
}

那里看看了广大的Element,在Xml解析时候就有Element这几个定义。在Java源文件中壹律有Element概念:

package com.example;        // PackageElement

public class MyClass {      // TypeElement

    private int a;          // VariableElement

    private Foo other;      // VariableElement

    public Foo () {}        // ExecuteableElement

    public void setA (      // ExecuteableElement
                int newA    // TypeElement
                ) {

    }
}

接下去正是在总计机的process中分析表明了
老是解析前都要清空,因为process方法只怕持续走一遍。
得到注明模型之后遍历调用生成Java代码

@Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        mAnnotatedClassMap.clear();
        try {
            processBindView(roundEnv);
        } catch (IllegalArgumentException e) {
            error(e.getMessage());
            return true;
        }

        try {
            for (AnnotatedClass annotatedClass : mAnnotatedClassMap.values()) {
                info("generating file for %s", annotatedClass.getFullClassName());
                annotatedClass.generateFinder().writeTo(mFiler);
            }
        } catch (Exception e) {
            e.printStackTrace();
            error("Generate file failed,reason:%s", e.getMessage());
        }
        return true;
    }

processBindView 和 getAnnotatedClass

    /**
     * 遍历目标RoundEnviroment
     * @param roundEnv
     */
    private void processBindView(RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(BindView.class)) {
            AnnotatedClass annotatedClass = getAnnotatedClass(element);
            BindViewField field = new BindViewField(element);
            annotatedClass.addField(field);
        }
    }
    /**
     * 如果在map中存在就直接用,不存在就new出来放在map里
     * @param element
     */
    private AnnotatedClass getAnnotatedClass(Element element) {
        TypeElement encloseElement = (TypeElement) element.getEnclosingElement();
        String fullClassName = encloseElement.getQualifiedName().toString();
        AnnotatedClass annotatedClass = mAnnotatedClassMap.get(fullClassName);
        if (annotatedClass == null) {
            annotatedClass = new AnnotatedClass(encloseElement, mElementUtils);
            mAnnotatedClassMap.put(fullClassName, annotatedClass);
        }
        return annotatedClass;
    }

叁.在生成Java在此之前 大家要在bindview-api 中开创一些类,协作bindview-compiler 一起利用。
您在行使Butterknife的时候不是要在onCreate里掉用一下BindView.bind(this)吗,那这么些东西是怎么呢。试想一下,前边做的一大堆工作是为着转移自动绑定控件的Java代码,假诺生成的Java代码不可能和您要动用的地点关系起来,那也是从未用的,能够把BindView.bind(this)驾驭为调用了你转移的Java代码,而生成了代码中达成了部分控件的初始化学工业作,自然你的控件就变得可用了。
接口:Finder 定义findView方法
实现类:ActivityFinder Activity中使用,ViewFinder View中使用
接口:Injector
inject方法未来是要创制在变更的Java文件中,用该办法中传送过来的参数进行控件的开头化。
协理类:ViewInjector 调用和传递参数
本条代码作者就不贴了,就一丝丝内容,1看就驾驭了。
4.在AnnotatedClass中生成Java代码
变动代码应用了3个很好用的库 Javapoet
。类,方法,都能够运用创设器创设出来,很好上手,再也不用拼接字符串了。哈哈哈哈~

public JavaFile generateFinder() {
        //构建方法
        MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder("inject")
                .addModifiers(Modifier.PUBLIC)//添加描述
                .addAnnotation(Override.class)//添加注解
                .addParameter(TypeName.get(mClassElement.asType()), "host", Modifier.FINAL)//添加参数
                .addParameter(TypeName.OBJECT, "source")//添加参数
                .addParameter(TypeUtil.FINDER, "finder");//添加参数

        for (BindViewField field : mFiled) {
            //添加一行
            injectMethodBuilder.addStatement("host.$N=($T)finder.findView(source,$L)", field.getFieldName()
                    , ClassName.get(field.getFieldType()), field.getResId());
        }

        String packageName = getPackageName(mClassElement);
        String className = getClassName(mClassElement, packageName);
        ClassName bindClassName = ClassName.get(packageName, className);
        //构建类
        TypeSpec finderClass = TypeSpec.classBuilder(bindClassName.simpleName() + "$$Injector")//类名
                .addModifiers(Modifier.PUBLIC)//添加描述
                .addSuperinterface(ParameterizedTypeName.get(TypeUtil.INJECTOR, TypeName.get(mClassElement.asType())))//添加接口(类/接口,范型)
                .addMethod(injectMethodBuilder.build())//添加方法
                .build();

        return JavaFile.builder(packageName, finderClass).build();
    }

    public String getPackageName(TypeElement type) {
        return mElementUtils.getPackageOf(type).getQualifiedName().toString();
    }

    private static String getClassName(TypeElement type, String packageName) {
        int packageLen = packageName.length() + 1;
        return type.getQualifiedName().toString().substring(packageLen).replace('.', '$');
    }

能够在代码里System.out调节和测试表明处理器的代码。
还要小心的有些,项目里面的相互引用。
bindview-complier 引用 bindview-annotation
app 引用了剩下的多少个module,在引用 bindview-complier 的时候用的apt的不二等秘书诀

apt project(':bindview-compiler')

就写到那里呢,Demo
放在 Github上了

  ((System.ComponentModel.ISupportInitialize)(this.performanceCounter1)).EndInit();

叁、随时四处笔者也能扩展—HtmlHelper扩展方法简介

  这一个艺术尽管简单的讲,不过会出错。

3.壹 扩充方法简介

  借助MSDN的介绍:“扩大方法使您可见向现有项目“添加”方法,而无需创造新的派生类型、重新编写翻译或以其余方法修改原始类型。”扩展方法是一种特殊的静态方法,但能够像扩大项目上的实例方法1致实行调用。大家能够回去第三有的对HtmlHelper的恢宏类-InputExtension类上,它是对此HtmlHelper的恢宏,那么怎么分辨它是HtmlHelper的扩充呢?

  原因是,当你添加performanceCounte之类的控件时,它会要求生成CategoryName,但VS突然犯傻,没有自动生成CategoryName,所以报了错。(CategoryName指的正是控件要用的名字)

叁.2 扩大方法的3要素

亚洲必赢官网 6

  (1)静态类

  能够从上海教室看出,InputExtension首先是2个静态类;

  (2)静态方法

  既然是静态类,那么其有着的艺术肯定皆以静态方法,例如:public
static MvcHtmlString CheckBox();

  (3)this关键字

  能够从章程名定义中看出,第三个参数都以this
HtmlHelper htmlHelper,代表对HtmlHelper类的增添;

 

三.三 自定义扩大方法

  (一)在Models文件夹下新建一个类,取名称为:MyHtmlHelperExt

  (二)将MyHtmlHelperExt设置为static,并写入以下的二个静态方法:

public static HtmlString MyExtHtmlLabel(this HtmlHelper helper, string value)  {        return new HtmlString(string.Format("Hello-{0}-End", value));  }

  (3)鲜明满足了扩展方法的叁要素之后,将命名空间改为:System.Web.Mvc。

namespace System.Web.Mvc

data-source=”Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.”>PS:何以要改命名空间为System.Web.Mvc?

data-source=”Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.”>那是因为1旦不改命名空间,大家要动用自定义的恢弘方法须求在各样页面中引进Models(MyHtmlHelper所在的百般命名空间)那个命名空间,为了防患重复的命名空间引进操作(想想我们采用Html.TextBox()不也远非引入命名空间么?),于是大家将命名空间与HtmlHelper类所在的命名空间保持壹致。

  (四)在页面中大家就能够选择大家团结写的扩大方法了

<%: Html.MyExtHtmlLabel("EdisonChou") %>

  (5)查看页面效果

亚洲必赢官网 7

贰、稳妥的化解办法

参考文章

(1)马伦,《ASP.Net
MVC视频教程》,

(二)oer,《HtmlHelper使用全称》,

(三)MSDN,《扩充方法(C#编制程序指南)》,

(4)MSDN,《HtmlHelper类(System.Web.Mvc)》,

 

作者:周旭龙

出处:

本文版权归小编和新浪共有,欢迎转载,但未经我同意必须保留此段申明,且在小说页面鲜明地点给出原著链接。


  在Form1.Designer中添加
    this.performanceCounter1.CategoryName = “Processor”;
    this.performanceCounter1.CounterName = “% Processor Time”;
    this.performanceCounter1.InstanceName = “_Total”;

  

 

————————————假装那是一个分割线————————————

亚洲必赢官网 8

网站地图xml地图