一小时搞精晓申明处理器,HtmlHelper与恢弘方法

By admin in 4858.com on 2019年3月27日

 

一 、2个功效强大的页面开发协助类—HtmlHelper初阶领会

HTML扩大类的兼具办法都有三个参数:
以textbox为例子
public static string TextBox( this HtmlHelper htmlHelper, string name,
Object value, IDictionary<string, Object> htmlAttributes )
一小时搞精晓申明处理器,HtmlHelper与恢弘方法。public static string TextBox( this HtmlHelper htmlHelper, string name,
Object value, Object htmlAttributes )
那1个参数代表那一个html标签的性质集合。使用方法如下。
 
1.ActionLink
<%=Html.ActionLink(“那是3个接连”, “Index”, “Home”)%>
带有QueryString的写法
<%=Html.ActionLink(“那是叁个总是”, “Index”, “Home”, new { page=1
},null)%>
<%=Html.ActionLink(“那是二个连接”, “Index”, new { page=1 })%>
有其它Html属性的写法
<%=Html.ActionLink(“那是3个接连”, “Index”, “Home”, new { id=”link1″
})%>
<%=Html.ActionLink(“这是1个老是”, “Index”,null, new { id=”link1″
})%>
QueryString与Html属性同时设有
<%=Html.ActionLink(“那是二个总是”, “Index”, “Home”, new { page = 1 },
new { id = “link1” })%>
<%=Html.ActionLink(“那是1个延续”, “Index” , new { page = 1 }, new {
id = “link1” })%>
 
变迁结果为:
<a href=”/”>那是1个连连</a>
带有QueryString的写法
<a href=”/?page=1″>那是多个老是</a>
<a href=”/?page=1″>那是三个连接</a>
有其余Html属性的写法
<a href=”/?Length=4″ id=”link1″>那是2个接连</a>
<a href=”/” id=”link1″>那是八个总是</a>
QueryString与Html属性同时存在
<a href=”/?page=1″ id=”link1″>那是1个连连</a>
<a href=”/?page=1″ id=”link1″>那是3个三番五次</a>
 
2.RouteLink
跟ActionLink在效劳上一样。
<%=Html.RouteLink(“关于”, “about”, new { })%>
带QueryString
<%=Html.RouteLink(“关于”, “about”, new { page = 1 })%>
<%=Html.RouteLink(“关于”, “about”, new { page = 1 }, new { id =
“link1” })%>
4858.com , 
变迁结果:
<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>
 
9.Partial
视图模板
webform里叫自定义控件。功用都以为着复用。但选拔上自定义控件真的很难用好。
<% Html.RenderPartial(“DinnerForm”);
%>  看精晓了未曾等号的。

Java中的注解是个很神奇的事物,还不打听的可以看下一时辰搞通晓自定义注脚(Annotation)。以后众多Android的库都用利用表明达成的,比如ButterKnife,大家不防也来上学一下,学完注脚处理器,大家尝试写一个简单易行的好像ButterKnife的事物来绑定控件。

群里一小伙伴在开发APP时遇见了难题,便截图提问

1.1 有失必有得

4858.com 1

  在ASP.Net
MVC中微软并从未提供类似服务器端控件那种开发方式,毕竟微软的MVC便是历史观的伏乞处理响应的回归。所以抛弃在此之前的那种事件响应的模子,扬弃服务器端控件也自然。

  但是,假若手写Html标签功效又比较低,可重成本比较低。那时,大家该怎么来提升作用呢?首先,经过上篇我们知晓能够由此ViewData传递数据,于是大家能够写出以下的Html代码:

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

  即便上述代码能够解决难题,不过效用依旧比较低,特别是在列表集合项较多的时候,工作量会相比大。那么,还有木有一种更好的法子呢?别急,微软一度为大家想好了国策。微软为开发职员快捷支付前台页面提供了加上的HtmlHelper的拉扯类,支持我们急忙支付前台页面,也提供了可扩展的接口,前台页面的价签能够可以达成高度可选择

哪些是注脚处理器?

注明处理器是(Annotation Processor)是javac的3个工具,用来在编译时环顾和编译和拍卖评释(Annotation)。你能够本人定义申明和注释处理器去搞一些业务。一个注明处理器它以Java代码也许(编写翻译过的字节码)作为输入,生成文书(通常是java文件)。那些生成的java文件不可能改改,并且会同其手动编写的java代码一样会被javac编写翻译。看到此间丰盛在此以前知道,应该明了大致的经过了,便是把标记了诠释的类,变量等作为输入内容,经过评释处理器处理,生成想要生成的java代码。

4858.com 2

1.2 HtmlHelper初窥

  大家能够通过在页面中经过Html.XXX来兑现火速的Html标签编辑,并且能够方便地实行数量绑定。

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

  那么,为啥能够在页面中调用Html.XXX方法吧?通过ILSpy反编写翻译ViewPage页,我们能够看看原来在ViewPage下有二个HtmlHelper类型的属性-Html。(那下终于通晓,为何能够在页面中使用Html.xxxx()了)

4858.com 3

  那么这几个HtmlHelper类又是1个哪些品种的大神啊?继续反编写翻译查看,在System.Web.Mvc命名空间下的HtmlHelper类型如下图所示,经过MSDN大神的上课,HtmlHelper帮忙在视图中展现HTML
控件。那大家看看在此类中有木有轶事中的TextBox、CheckBox的点子吗?经查阅,木有。

4858.com 4

  那么,大家怎么能够在页面中利用Html.Text博克斯()方法吗?这里就涉嫌到多少个称作“扩张方法”的东东了,HtmlHelper 类的恢宏方法在 System.Web.Mvc.Html
命名空间中。 这么些扩展添加了用来创设窗体、彰显 HTML
控件、呈现分部视图、执行输入验证等成效的帮忙器方法。那么,有关怎么着自定义扩张方法请参阅本文第②部分,那里先卖个关子,暂不介绍。

4858.com 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()
    内定申明处理器是挂号给那个评释的,它是2个字符串的集合,意味着可以帮忙七个类其他诠释,并且字符串是法定全名。
  • getSupportedSourceVersion 指定Java版本
  • process(Set<? extends TypeElement> annotations,
    RoundEnvironment roundEnv)
    这一个也是最关键的,在此地扫描和处理你的注释并生成Java代码,音信都在参数RoundEnvironment
    里了,前面会介绍。

在Java7 中还足以选用

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

取代 getSupportedSourceVersion() 和 getSupportedAnnotationType()
,没毛病,还足以在诠释处理离器中采纳表明。

① 、傻瓜式化解办法:

1.3 为何使用HtmlHelper?

   思考那样3个场馆:我们的花色第3个本子中的路由规则是这么的{controller}/{action}/{id},于是大家项目中保有的<a>标签所指向的都以以刚刚的条条框框命名的href(例如:<a
></a>)。不过在第③版中,大家的路由规则也会化为了{controller}-{action}-{id},那么大家恰好为超链接所设置的href便都心有余而力不足寻常访问了。那时,大家需求展开调换,单个替换或批量交替(例如改为:<a
></a>),即使也得以消除难题,不过的确增添了工作量,成效十分的低。

  那么,怎么样来遮掩那种变更所推动的不方便呢?那里,通过应用HtmlHelper为大家提供的ActionLink标签,便足以缓解这一个题材。因为HtmlHelper是从服务器端自动帮您生成a标签,因而所生成的href会服从如今的路由规则,也就帮大家遮挡了变动,升高了工效。

挂号表明处理器

卷入注明处理器的时候须求2个卓越的公文
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提供了贰个挂号处理器的库

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

贰个评释消除:

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

读到那里ButterKnife用到的知识点大家都早已领悟了
1.自定义表明
2.用证明处理器解析注脚
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;
    }
}

接下去我们创建二个品种,写一个回顾的用申明绑定控件的事例

  删除:

贰 、没有服务器控件也能干大事—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在用法差不离与ActionLink一致,那里就不再介绍,详情请加入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.Text博克斯For(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等。关于别的的法子介绍,请自行检索,那里不再一一赘述。

品种组织

--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

1.在 bindview-annotation
下创建二个@BindView注解,该声明重临五个值,整型,名字为value,用来代表控件ID。

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

2.在 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用来标记类成员,二个类下能够有七个成员,好比二个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('.', '$');
    }
}

成员用BindView菲尔德表示,没什么复杂的逻辑,在构造函数判断项目和开首化,不难的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;
    }

3.在生成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 调用和传递参数
其一代码作者就不贴了,就一丢丢内容,一看就知晓了。
4.在AnnotatedClass中生成Java代码
变动代码应用了贰个很好用的库 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.1 扩张方法简介

  借助MSDN的介绍:“恢宏方法使你能够向现有项目“添加”方法,而无需创造新的派生类型、重新编写翻译或以其余格局修改原始类型。”增添方法是一种独特的静态方法,但能够像扩大类型上的实例方法同样进行调用。大家得以回来第3有些对HtmlHelper的壮大类-InputExtension类上,它是对于HtmlHelper的扩大,那么怎么辨识它是HtmlHelper的扩张呢?

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

3.2 扩张方法的三要素

4858.com 6

  (1)静态类

  可以从上海教室看出,InputExtension首先是四个静态类;

  (2)静态方法

  既然是静态类,那么其独具的章程肯定都是静态方法,例如:public
static MvcHtmlString CheckBox();

  (3)this关键字

  能够从点子名定义中看出,第二个参数都以this
HtmlHelper htmlHelper,代表对HtmlHelper类的扩充;

 

3.3 自定义扩展方法

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

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

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.”>那是因为只要不改命名空间,大家要选用自定义的恢弘方法须要在每种页面中引入Models(MyHtmlHelper所在的不得了命名空间)那个命名空间,为了以免重复的命名空间引入操作(想想大家使用Html.TextBox()不也没有引入命名空间么?),于是大家将命名空间与HtmlHelper类所在的命名空间保持一致。

  (4)在页面中大家就可以动用大家和好写的扩充方法了

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

  (5)查看页面效果

4858.com 7

② 、妥帖的化解办法

参照文章

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

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

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

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

 

作者:周旭龙

出处:

正文版权归小编和网易共有,欢迎转载,但未经笔者同意必须保留此段证明,且在篇章页面明显地点给出原作链接。


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

  

 

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

4858.com 8

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有