Java反射詳解

来源:https://www.cnblogs.com/mengd/archive/2020/07/29/13400005.html
-Advertisement-
Play Games

一、反射概述 1. java.lang.Class:是反射的源頭 我們創建一個類,通過編譯,生成對應的.calss文件,之後使用java.exe載入(jvm的類載入器)此.class文件,此.class文件載入到記憶體以後,就是一個運行時類,存在緩存區,那麼這個運行時類的本身就是一個class的實例 ...


一、反射概述

1. java.lang.Class:是反射的源頭

我們創建一個類,通過編譯,生成對應的.calss文件,之後使用java.exe載入(jvm的類載入器)此.class文件,此.class文件載入到記憶體以後,就是一個運行時類,存在緩存區,那麼這個運行時類的本身就是一個class的實例

  • 每一個運行時類只載入一次
  • 有了Class實例以後,我們才可以進行如下的操作:
    • 創建對應的運行時類的對象(重點)
    • 可以獲取對象的運行時類的完整結構(屬性、方法、構造器、內部類、、、)(理解)
    • 調用對應的運行時類的指定的結構(屬性、方法)(重點)

在反射以前,如何創建一個類的對象,並調用其中的方法屬性

public void test1() {
		Person p = new Person();
		p.setAge(10);
		p.setName("AA");
		p.show();
		System.out.println(p);
	}

有了反射,可以通過反射創建一個類的對象,並調用其中的方法,下麵詳細說

public void test2() throws Exception {
		
		Class clazz = Person.class;
		
		//1.創建clazz對應的運行時類Person類的對象
		Person p = (Person)clazz.newInstance();
		System.out.println(p);
		
		//2.通過反射調用運行時類的指定屬性,public name的修改方式
		Field f1 = clazz.getField("name");
		f1.set(p, "LiuDaHua");
		System.out.println(p);
		
		//private age的方式
		Field f2 = clazz.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(p, 20);
		System.out.println(p);
		
		//3.通過反射調用運行時類的指定方法 public修飾的
		Method m1 = clazz.getMethod("show");
    	// 執行
		m1.invoke(p);
    	// 帶參數的方法
		Method m2 = clazz.getMethod("display", String.class);
		m2.invoke(p, "cn");
		
	}
	

二、如何獲取Class的實例

1.調用運行時類本身的.class屬性

Class clazz = Person.class;
System.out.println(clazz.getName());
		
Class clazz1 = String.class;
System.out.println(clazz1.getName());

2.通過運行時類的對象獲取

Person p = new Person();
Class clazz2 = p.getClass();
System.out.println(clazz.getName());

3.通過Class的靜態方法獲取,通過此方式,體會反射的動態性

String className = "com.atguigu.java.Person";
		
Class clazz4 = Class.forName(className);	   
System.out.println(clazz4);


4.通過類的載入器

ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz5 = classLoader.loadClass(className);
System.out.println(clazz5.getName());

整個代碼

public void test4() throws Exception {
		//1.調用運行時類本身的.class屬性
		Class clazz = Person.class;
		System.out.println(clazz.getName());
		
		Class clazz1 = String.class;
		System.out.println(clazz1.getName());
		
		//2.通過運行時類的對象獲取
		Person p = new Person();
		Class clazz2 = p.getClass();
		System.out.println(clazz.getName());
		
		//3.通過Class的靜態方法獲取,通過此方式,體會反射的動態性
		String className = "com.atguigu.java.Person";
		
		Class clazz4 = Class.forName(className);
		System.out.println(clazz4);
		
		
		//4.通過類的載入器
		ClassLoader classLoader = this.getClass().getClassLoader();
		Class clazz5 = classLoader.loadClass(className);
		System.out.println(clazz5.getName());
	}
	

三、創建運行時類對象

1. 獲取Class的實例

通常直接使用類名.class , 例如Person.class

當然了,上面的幾種方法都是可以的

String className = "com.atguigu.java.Person";
Class clazz = Class.forName(className);

2.創建運行時類對象

創建對應的運行時類的對象,使用的是newInstance(),實際上就是運用了運行時類的空參數的構造器

要想能夠創建成功

  • 要求對應的運行時類要有空參數的構造器
  • 構造器的許可權修飾符的許可權要足夠
Object obj = clazz.newInstance();//調用的是空參構造器
Person p = (Person)obj;
System.out.println(p);

全部代碼

public void test1() throws Exception {
	// 獲取Class實例
   		Class clazz = Person.class;
		
		//創建對應的運行時類的對象,使用的是newInstance(),實際上就是運用了運行時類的空參數的構造器
		//要想能夠創建成功,①要求對應的運行時類要有空參數的構造器,②構造器的許可權修飾符的許可權要足夠
		Object obj = clazz.newInstance();//調用的是空參構造器
		Person p = (Person)obj;
		System.out.println(p);		
	}

四、通過反射獲取類的完整結構

1.獲取運行時類的屬性

1.getFields() 返回 :表示公共欄位的 Field 對象的數組,只能獲取運行時類中以及父類中聲明的為public的屬性

Field[] fiels = clazz.getFields();
for(int i=0;i<fiels.length;i++) {
    System.out.println(fiels[i]);
	}

2.getDeclaredFields() :獲取運行時類本身聲明的所有的屬性,包括私有的

Field[] fiels1 = clazz.getDeclaredFields();
for(int i=0;i<fiels1.length;i++) {
	System.out.println(fiels1[i].getName());
	}
		//增強for迴圈
for(Field f:fiels1) {
	System.out.println(f.getName());
}

2.獲取屬性的各個部分的內容

許可權修飾符 變數類型 變數名

1.獲取每個屬性的許可權修飾符

Field[] field = clazz.getDeclaredFields();
	for(Field i:field) {
	//1.獲取每個屬性的許可權修飾符
		int a = i.getModifiers();
		String str1 = Modifier.toString(a);
		System.out.print(str1+"   ");
	}

2.獲取屬性的變數類型

Field[] field = clazz.getDeclaredFields();
		for(Field i:field) {
		//2.獲取屬性的變數類型
		Class type = i.getType();
		System.out.print(type+"  ");
	}

3.獲取屬性名

Class clazz = Person.class;
		Field[] field = clazz.getDeclaredFields();
		for(Field i:field) {
		//3.獲取屬性名
		System.out.print(i.getName());
		System.out.println();
	}
	

3.獲取運行時類的方法(重點)

1.getMethods() 獲取運行時類及其父類中所有聲明為public的方法

Class clazz = Person.class;
Method[] m1 = clazz.getMethods();
	for(Method m:m1) {
	System.out.println(m);
	}

2.getDeclaredMethods() 獲取運行時類本身聲明的所有的方法

Method[] methods = clazz.getDeclaredMethods();
	for(int i=0;i<methods.length;i++) {
		System.out.println(methods[i]);
	}

4.獲取方法的各個部分的內容

註解 許可權修飾符 返回值類型 方法名 形參列表 異常

1.註解

Class clazz = Person.class;
		
	Method[] m1 = clazz.getMethods();
	for(Method m:m1) {
	Annotation[] an = m.getAnnotations();
	for(Annotation a:an) {
	    System.out.println(a);
	}
}

2.許可權修飾符

int a = m.getModifiers();
String str1 = Modifier.toString(a);
System.out.print(str1+"  ");

3.返回值類型

Class return1 = m.getReturnType();
System.out.print(return1+"  ");

4.方法名

System.out.print(m.getName()+"   ");

5.形參列表

System.out.print("(");
Class[] params = m.getParameterTypes();
for(Class p : params) {
	System.out.print(p.getName());
}
System.out.println(")"+"   ");

6.拋的異常

Class[] ex = m.getExceptionTypes();
	for(Class e:ex) {
		System.out.print(e.getName());
	}
 //   for(int i=0;i<ex.length;i++) {
//	System.out.print(ex[i].getName());
 //       }

5.獲取構造器

	@Test
	public void test5() throws Exception {
		
		Class clazz = Class.forName("com.atguigu.java.Person");
		
		Constructor[] cons = clazz.getDeclaredConstructors();
		for(Constructor c : cons) {
			System.out.println(c);
		}
		
	
	}

6.獲取運行時類的父類

@Test
	public void test6() {
		Class clazz = Person.class;
		Class super1 = clazz.getSuperclass();
		System.out.println(super1);
	}

7.獲取帶泛型的父類

@Test
	public void test7() {
		Class clazz = Person.class;
		Type type1 = clazz.getGenericSuperclass();
		System.out.println(type1);
	}

8.獲取父類的泛型(重點)

@Test
	public void test8() {
		Class clazz = Person.class;
		Type type1 = clazz.getGenericSuperclass();
		
		ParameterizedType param= (ParameterizedType)type1;
		Type[] ars = param.getActualTypeArguments();
		System.out.println((Class)ars[0]);
	}

9.獲取實現的介面

@Test
	public void test9() {
		Class clazz = Person.class;
		Class[] i = clazz.getInterfaces();
		for(Class a:i) {
			System.out.println(a);
		}
	}

10.獲取所在的包

@Test
	public void test10() {
		Class clazz = Person.class;
		Package p = clazz.getPackage();
		System.out.println(p);
	}

全部代碼如下:

package com.atguigu.java;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.junit.Test;

/**
 * 通過反射獲取類的完整結構
 * 
 * @author MD
 *
 */
public class TestField {

	
	/**
	 * 1.獲取運行時類的屬性
	 */
	@Test
	public void test1() {
		Class clazz = Person.class;
		
		//1.getFields() 返回 :表示公共欄位的 Field 對象的數組 
		// 只能獲取運行時類中以及父類中聲明的為public的屬性
//		Field[] fiels = clazz.getFields();
//		for(int i=0;i<fiels.length;i++) {
//			System.out.println(fiels[i]);
//		}
		
		//2.getDeclaredFields() :獲取運行時類本身聲明的所有的屬性
		Field[] fiels1 = clazz.getDeclaredFields();
		for(int i=0;i<fiels1.length;i++) {
			System.out.println(fiels1[i].getName());
		}
		//增強for迴圈
		for(Field f:fiels1) {
			System.out.println(f.getName());
		}
		
				
	}
	
	/**
	 * 許可權修飾符 變數類型  變數名
	 * 2.獲取屬性的各個部分的內容
	 * 
	 */
	
	@Test
	public void tset2() {
		Class clazz = Person.class;
		Field[] field = clazz.getDeclaredFields();
		for(Field i:field) {
			//1.獲取每個屬性的許可權修飾符
			int a = i.getModifiers();
			String str1 = Modifier.toString(a);
			System.out.print(str1+"   ");
			//2.獲取屬性的變數類型
			Class type = i.getType();
			System.out.print(type+"  ");
			//3.獲取屬性名
			System.out.print(i.getName());
			System.out.println();
		}
	}
	
	
	
	
	
	/**
	 * 3.獲取運行時類的方法
	 */
	@Test
	public void test3() {
		Class clazz = Person.class;
		
		//1.getMethods() 獲取運行時類及其父類中所有聲明為public的方法
		
//		Method[] m1 = clazz.getMethods();
//		for(Method m:m1) {
//			System.out.println(m);
//		}
			

		//2.getDeclaredMethods() 獲取運行時類本身聲明的所有的方法
		Method[] methods = clazz.getDeclaredMethods();
		for(int i=0;i<methods.length;i++) {
			System.out.println(methods[i]);
		}
	}
	
	/**
	 * 4.獲取方法的各個部分的內容
	 * 註解  許可權修飾符   返回值類型	方法名    形參列表    異常
	 * 
	 */
	@Test
	public void test4() {
		Class clazz = Person.class;
		
		Method[] m1 = clazz.getMethods();
		for(Method m:m1) {
			//1.註解
			Annotation[] an = m.getAnnotations();
			for(Annotation a:an) {
				System.out.println(a);
			}
						
			//2.許可權修飾符
			int a = m.getModifiers();
			String str1 = Modifier.toString(a);
			System.out.print(str1+"  ");
			
			//3.返回值類型
			Class return1 = m.getReturnType();
			System.out.print(return1+"  ");
			
			
			//4.方法名
			System.out.print(m.getName()+"   ");
						
			//5.形參列表
			System.out.print("(");
			Class[] params = m.getParameterTypes();
			for(Class p : params) {
				System.out.print(p.getName());
			}
			System.out.println(")"+"   ");
			
			//6.拋的異常
			Class[] ex = m.getExceptionTypes();
			for(Class e:ex) {
				System.out.print(e.getName());
			}
//			for(int i=0;i<ex.length;i++) {
//				System.out.print(ex[i].getName());
//			}
			
			System.out.println();
		}
		
		
	}

	/**
	 * 5.獲取構造器
	 * @throws Exception 
	 */
	
	@Test
	public void test5() throws Exception {
		
		Class clazz = Class.forName("com.atguigu.java.Person");
		
		Constructor[] cons = clazz.getDeclaredConstructors();
		for(Constructor c : cons) {
			System.out.println(c);
		}
	}

	/**
	 * 
	 * 6.獲取運行時類的父類
	 */
	@Test
	public void test6() {
		Class clazz = Person.class;
		Class super1 = clazz.getSuperclass();
		System.out.println(super1);
	}
	
	
	/**
	 * 7.獲取帶泛型的父類
	 */
	
	@Test
	public void test7() {
		Class clazz = Person.class;
		Type type1 = clazz.getGenericSuperclass();
		System.out.println(type1);
	}
	
	
	/**
	 * 8.獲取父類的泛型
	 */
	@Test
	public void test8() {
		Class clazz = Person.class;
		Type type1 = clazz.getGenericSuperclass();
		
		ParameterizedType param= (ParameterizedType)type1;
		Type[] ars = param.getActualTypeArguments();
		System.out.println((Class)ars[0]);
	}
	
	/**
	 * 9.獲取實現的介面
	 */
	@Test
	public void test9() {
		Class clazz = Person.class;
		Class[] i = clazz.getInterfaces();
		for(Class a:i) {
			System.out.println(a);
		}
	}
	
	/**
	 * 10.獲取所在的包
	 */
	@Test
	public void test10() {
		Class clazz = Person.class;
		Package p = clazz.getPackage();
		System.out.println(p);
	}
}


五、調用運行時類的指定結構

1.調用運行時類指定的屬性並賦值

1. 獲取指定的屬性

getField(String fieldName):獲取運行時類中聲明為public的指定的屬性名為fieldName的屬性

Field name = clazz.getField("name");

2.創建運行時類的對象

Person p = (Person) clazz.newInstance();
System.out.println(p);

3.將運行時類的指定屬性賦值

name.set(p, "Jerry");
System.out.println(p);

給age賦值,private需要註意

getDeclareField(String fieldName):獲取運行時類中指明為filedName的屬性

	Field age = clazz.getDeclaredField("age");
	//由於屬性許可權修飾符的限制,為了保證可以給屬性賦值,需要在操作前使得此屬性可被操作
	age.setAccessible(true);//私有的設置成可以訪問的
	age.set(p,1);
	System.out.println(p);

給id賦值,預設的修飾符

	Field id = clazz.getDeclaredField("id");
	id.set(p,10);
	System.out.println(p);

2.調用運行時類中指定的方法

1.getMethod(String methodName,Class...params)獲取指定的public方法,方法名,參數列表

Class clazz = Person.class;
Method m1 = clazz.getMethod("show");

2.創建運行時類的對象

Person p =(Person)clazz.newInstance();

3.和屬性相似,這裡是invoke關鍵字裡面是對象和參數列表,或許還有返回值,用Object接收

Object returnVal = m1.invoke(p);
System.out.println(returnVal);//沒返回值的列印為null

4.獲取toString()有返回值的

Method m2 = clazz.getMethod("toString");
Object returnVal1 = m2.invoke(p);
System.out.println(returnVal1);

5.獲取display()帶參數的

Method m3 = clazz.getMethod("display",String.class);
m3.invoke(p, "china");

6.獲取info()靜態的方法

Method m4 = clazz.getMethod("info");
m4.invoke(Person.class);

7.獲取Test() 私有的帶參數的有返回值的

Method m5 = clazz.getDeclaredMethod("Test",String.class,Integer.class);
m5.setAccessible(true);
Object o = m5.invoke(p,"測試",5);
System.out.println(o);

3.調用指定的構造器,創建類對象

public void test3() throws InstantiationException, Exception {
		Class clazz = Person.class;
		Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
		cons.setAccessible(true);
		Person p = (Person)cons.newInstance("迪麗熱巴",20);
		System.out.println(p);

		
	}

全部代碼

package com.atguigu.java;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * ******調用對應的運行時類的指定的結構(屬性、方法)
 * @author MD
 *
 */
public class TestField1 {
	/**
	 * 調用運行時類指定的屬性
	 * @throws Exception 
	 * @throws NoSuchFieldException 
	 */
	
	@Test
	public void test1() throws Exception {
		Class clazz = Person.class;
		
		//1.獲取指定的屬性
		//getField(String fieldName):獲取運行時類中聲明為public的指定的屬性名為fieldName的屬性
		Field name = clazz.getField("name");
		//2.創建運行時類的對象
		Person p = (Person) clazz.newInstance();
		System.out.println(p);
		//3.將運行時類的指定屬性賦值
		name.set(p, "Jerry");
		System.out.println(p);
		
		//給age賦值,private需要註意
		//getDeclareField(String fieldName):獲取運行時類中指明為filedName的屬性
		Field age = clazz.getDeclaredField("age");
		//由於屬性許可權修飾符的限制,為了保證可以給屬性賦值,需要在操作前使得此屬性可被操作
		age.setAccessible(true);//私有的設置成可以訪問的
		age.set(p,1);
		System.out.println(p);
				
		//給id賦值,預設的修飾符
		Field id = clazz.getDeclaredField("id");
		id.set(p,10);
		System.out.println(p);
		
	}
		
	/**
	 * 調用運行時類中指定的方法
	 * @throws Exception 
	 * @throws NoSuchMethodException 
	 */
	@Test
	public void test2() throws NoSuchMethodException, Exception {
		Class clazz = Person.class;
		
		//getMethod(String methodName,Class...params)獲取指定的public方法,方法名,參數列表
		Method m1 = clazz.getMethod("show");
		
		//創建運行時類的對象
		Person p =(Person)clazz.newInstance();
		
		//和屬性相似,這裡是invoke關鍵字裡面是對象和參數列表,或許還有返回值,用Object接收
		Object returnVal = m1.invoke(p);
		System.out.println(returnVal);
				
		//獲取toString()有返回值的
		Method m2 = clazz.getMethod("toString");
		Object returnVal1 = m2.invoke(p);
		System.out.println(returnVal1);
		
		//獲取display()帶參數的
		Method m3 = clazz.getMethod("display",String.class);
		m3.invoke(p, "china");
				
		//獲取info()靜態的方法
		Method m4 = clazz.getMethod("info");
		m4.invoke(Person.class);
				
		//獲取Test() 私有的帶參數的有返回值的
		Method m5 = clazz.getDeclaredMethod("Test",String.class,Integer.class);
		m5.setAccessible(true);
		Object o = m5.invoke(p,"測試",5);
		System.out.println(o);	
	}
	
	
	/**
	 * 調用指定的構造器,創建類對象
	 * @throws Exception 
	 * @throws InstantiationException 
	 */
	
	@Test
	public void test3() throws InstantiationException, Exception {
		Class clazz = Person.class;	
		Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
		cons.setAccessible(true);
		Person p = (Person)cons.newInstance("迪麗熱巴",20);
		System.out.println(p);
	}
}

六、ClassLoader

類載入器是用來把類(class)裝載進記憶體

1.獲取一個系統類載入器

ClassLoader loader1 = ClassLoader.getSystemClassLoader();
System.out.println(loader1);

2.獲取系統類載入器的父類載入器,即擴展類載入器

ClassLoader loader2 = loader1.getParent();
System.out.println(loader2);

3.獲取擴展類載入器的父類載入器,即引導類載入器,載入的是核心庫,列印為null

ClassLoader loader3 = loader2.getParent();
System.out.println(loader3);

4.測試當前類由哪個類載入器進行載入

Class clazz1 = Person.class;
ClassLoader loader4 = clazz1.getClassLoader();
System.out.println(loader4);//系統類載入器

1. 描述一下JVM載入class文件的原理機制?

JVM中類的裝載是由ClassLoader和它的子類來實現的,

Java ClassLoader 是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 必須使用英文開頭,並且開頭字母一律小寫 所有的命名最好都小寫 儘量不要用縮寫英,除非可以一目瞭然的 如果遇到相差不大 class或者id,主功能識別字母在前,位置識別字母在後,位置識別字母;第一個可大寫(如: navTop, menuLeft) 遵循駝峰命名法:第一個單詞的首字母小寫,其餘每一個有意 ...
  • 行為型模式 行為型模式關註於應用運行過程中演算法的提供和通信關係的梳理。 相比於創建型模式和結構型模式,行為型模式包含了最多的設計模式種類,包括: 職責鏈模式 模板方法模式 解釋器模式 命令模式 迭代器模式 中介者模式 備忘錄模式 觀察者模式 狀態模式 策略模式 訪問者模式 職責鏈模式 職責鏈模式為了 ...
  • 做項目時我們一直在說框架、架構,那它到底是什麼呢? 什麼是架構 從 dubbo 官網我們可以看到架構設計的發展演變史。 這裡把架構分成四類: 單一應用架構 垂直應用架構 分散式服務架構 流動計算架構 剛開始時 PHP + MySQL 就可以形成網站了。 這種模式支持中小型網站是沒有問題的,但是一旦形 ...
  • 事務處理 Spring Boot事務機制實質上就是Spring的事務處理機制。 1 事務的4大特性 原子性(Atomicity) 一個事務要麼全部提交成功,要麼全部失敗回滾,不能只執行其中的一部分操作。 一致性(Consistency) 一旦事務完成(不管成功還是失敗),系統必須確保涉及的數據處於一 ...
  • 一、printf()函數 常用的轉換說明 轉換說明 輸出 %a 浮點數,十六進位數和p計數法 %A 浮點數,十六進位數和p計數法 %c 單個字元 %d 有符號的十進位數 %e 浮點數,e計數法 %E 浮點數,e計數法 %f 浮點數,十進位計數法 %g 根據值的不同,自動選擇%f或者%e,%e格式用於 ...
  • 數據結構--二叉樹(Java) 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 樹的常用術語(結合示意圖理解) 節點 根節點 父節點 子節點 葉子節點 (沒有子節點的節點) 節點的權(節點值) 路徑(從root節點找到該節點的路 ...
  • from selenium import webdriver #import time driver=webdriver.Chrome() #最小化視窗 #driver.minimize_window() driver.get("https://www.douban.com/") #time.sle ...
  • 用了Win10的配置環境變數功能後,其比Win7的配置界面更直觀、更易操作與理解,特此更新併發布本篇文章。 如果你的電腦是Win7系統,請參考:在Win7上配置Path環境變數 我們說的環境變數,一般是指的是Path環境變數。 第一步:點擊“此電腦”,右鍵,“屬性” 第二步:點擊“高級系統設置”,彈 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...