中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

找人做網站需要注意網絡營銷的現(xiàn)狀分析

找人做網站需要注意,網絡營銷的現(xiàn)狀分析,門戶網站建設目標,網站建設怎么做呢接口隔離原則、反射、特性、依賴注入 接口隔離原則 客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。 五種原則當中的i 上一章中的接口,即契約。 契約就是在說兩件事,甲方說自己不會多要,乙方會在…

接口隔離原則、反射、特性、依賴注入

在這里插入圖片描述

接口隔離原則

客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。

五種原則當中的i

上一章中的接口,即契約。

契約就是在說兩件事,甲方說自己不會多要,乙方會在契約里說自己不會少給。


乙方的不會少給是比較容易做到的,作為服務的提供者,實現(xiàn)一個接口的時候,必須要實現(xiàn)接口里面的所有的方法,如果沒有實現(xiàn)所有的方法,那么就會留下抽象方法,自己就變成了一個抽象類,那么仍然不能夠實例化,不是一個完整的服務提供者,不是一個具體類。


實現(xiàn)了一個接口的完整服務提供者,接口里面的方法是一定必須實現(xiàn)的。乙方不能少給,這是強制性的,硬性的規(guī)定。如果有方法沒有實現(xiàn)完全,編譯器會檢查到報錯。


但是甲方不會多要,卻是一個軟性的規(guī)定。所以說這是一個設計方面的問題,需要使用設計原則去約束。 編譯器沒法去檢查,甲方是否多要了。


怎么才能知道,甲方有沒有多要呢?

就看傳給這個調用者的接口類型里,有沒有一直沒被調用到的方法成員。如果有,那就說明,傳進來的接口類型太大了,太胖了。換句話來說,當一個接口太胖了,那么這個接口就是由兩個或兩個以上的本質不同的小接口合并起來的。所以當把大接口傳進來之后,只有一部分被調用到了,而其中一部分就多余出來了。


這種大接口產生的原因的不同,違反接口隔離原則,所帶來的不好的后果有兩種。

第一種情況

胖接口設計的時候有問題,把太多的功能包含到這個接口里了。把這種含有太多功能的接口傳給調用者,這樣其中必然有一些功能調用不到。

這樣子的話,實現(xiàn)這個接口的類,同時也違反了,單一職責原則。


單一職責原則和接口隔離原則,就是一個硬幣的兩面,實際上就是一回事。

只是接口隔離原則,是從服務的調用者的角度上來看。單一職責原則,是站在服務提供者的角度上來看這個接口。

針對這種情況,我們的解決方法就是將胖接口拆分。拆分小接口,每個小接口都描述單一的功能。將本質不同的功能隔離開來,然后再使用接口封裝起來。

接口隔離原則:就是服務的調用者不會多要

using System;namespace IspExample {/* 背景故事:一個女生開車把車撞了* 她男朋友就哄她說,下次給她買個坦克開*/internal class Program {static void Main(string[] args) {/* 我們想要給driver傳入的是交通工具* 而不是想要傳入能開炮的東西* 所以這里是ITank接口設計的不合理* 應該讓ITank繼承IVehicle*/Driver driver = new Driver(new Car());driver.Drive();Console.ReadKey();}}/* 此時我們想讓Driver類* 也能開Tank,無論怎么改都要改動Driver類* 假如直接將IVehicle接口改為ITanke接口* 那么的確可以使用這個接口,開坦克了,但是這樣* 就傳進來了一個胖接口,因為那個女生開坦克是當做車開的* Fire方法永遠都不會被調用到了* 那么這個設計就違反了接口隔離原則* 解決辦法就是,將這個胖接口,分成兩個小接口*/class Driver {private IVehicle _vehicle;public Driver(IVehicle vehicle){_vehicle = vehicle;}public void Drive() {_vehicle.Run();}}interface IVehicle {void Run();}class Car : IVehicle {public void Run() {Console.WriteLine("Car is running...");}}class Truck : IVehicle {public void Run() {Console.WriteLine("Truck is running...");}}interface IWeapon{void Fire();}/* 繼承多個接口* 讓ITank既繼承自IVehicle又繼承自IWeapon*/interface ITank : IVehicle, IWeapon{}//原本的ITank//interface ITank {//    void Fire();//    void Run();//}class LightTank : ITank {public void Fire() {Console.WriteLine("Boom!");}public void Run() {Console.WriteLine("Ka ka ka...");}}class MediumTank : ITank {public void Fire() {Console.WriteLine("Boom!!");}public void Run() {Console.WriteLine("Ka! ka! ka!...");}}class HeavyTank : ITank {public void Fire() {Console.WriteLine("Boom!!!");}public void Run() {Console.WriteLine("Ka!! ka!! ka!!...");}}
}

注:在使用接口隔離原則和單一職責原則的時候,不要過猶不及。如果玩得過火了的話,就會產生很多很細碎的里面只有一個方法的接口和類

第二種情況

傳入的接口有問題

本應該傳一個小接口,結果卻傳了一個將幾個小接口合并起來的大接口。

這可能導致的問題就是,把一些原本合格的服務的提供者當在門外了

就比如上一個例子中,將Driver中的代碼,改成這種

那么就服務的提供者就沒有了CarTruck這兩個了

class Driver {private ITank _tank;public Driver(ITank tank){_tank = tank;}public void Drive() {_tank.Run();}}
using System;
using System.Collections;namespace IspExample2 {/* 之前有個例子中* 要求計算一組整數(shù)的和,* 接口對服務調用者的約束就是,這組整數(shù)能夠被迭代* 也就是要求,組整數(shù)的類型實現(xiàn)了IEnumerable接口*/internal class Program {static void Main(string[] args) {int[] nums1 = { 1, 2, 3, 4, 5};ArrayList nums2 = new ArrayList { 1, 2, 3, 4, 5 };var nums3 = new ReadOnlyCollection(nums1);Console.WriteLine(Sum(nums1));Console.WriteLine(Sum(nums2));Console.WriteLine(Sum(nums3));/* 此時,Sum這個方法是沒辦法處理nums3的* 因為設置的傳入接口太胖了* 我們自己定義的集合只繼承了IEnumerable接口* 而沒有繼承ICollection接口* 我們實際上,只需要有迭代器的數(shù)據(jù)類型就能夠傳入* 所以不應該將傳入的接口設置的這么胖*/}//static int Sum(ICollection nums)//原本設置的接口//下面是更改后的接口static int Sum(IEnumerable nums) {int sum = 0;foreach (int i in nums) {sum += i;}return sum;}}//有可能我們會設計出一個只實現(xiàn)了IEnumerable接口//而沒有實現(xiàn)ICollection接口的類//自己寫一個只讀的集合class ReadOnlyCollection : IEnumerable {private int[] _array;public ReadOnlyCollection(int[] array){_array = array;}//當外界迭代的時候,需要給一個迭代器public IEnumerator GetEnumerator() {return new Enumerator(this);}public class Enumerator : IEnumerator {private ReadOnlyCollection _collection;private int _head;public Enumerator(ReadOnlyCollection collection){_collection = collection;_head = -1;/* 為什么要初始化為-1是有原因的* 迭代器是先調用判斷是否越界的方法的* 而這個時候++_head,然后讀取數(shù)組的值的時候,就正好是1了*/}//只讀屬性public object Current {get {/* 這個屬性需要拿到傳進集合的數(shù)組,* 所以是必須傳進來一個collection的* 因為要求返回為Object,所以還不能直接返回整數(shù)類型,需要裝箱*/Object o = _collection._array[_head];//_head++;return o;}}public bool MoveNext() {if (++_head < _collection._array.Length)return true;else return false;}public void Reset() {_head = -1;}}}
}

第三種情況

專門用來展示,顯式接口實現(xiàn)


c#語言在接口隔離方面,做得比其他語言都要好,都要徹底。不但能做到接口隔離,甚至還能做到把隔離出來的接口隱藏起來。

直到顯式的使用這種接口類型的變量,去引用一個實現(xiàn)了這個接口的具體類的實例的時候,這個接口內的方法才能被看見,才能被使用。


殺手不太冷的主角,一面是暖男,一面是冷酷無情的殺手

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IspExample3 {/* 愛憎分明的殺手* 一面是暖男* 另一面是冷酷無情的*/internal class Program {static void Main(string[] args) {/* 從設計的角度來講* 殺手在大街上不應該被人隨便就能認出來* 即,Kill()方法,不應該能顯示出來。* 如果一個接口的方法,我們不想被人輕易地調用的話* 就不應該被人輕易地看到*/IKiller killer = new WarmKiller();killer.Kill();//如果想要調用Love方法有以下幾種方式:var wk = (IGentleman)killer;//var wk = (WarmKiller)killer;//var wk = killer as WarmKiller;wk.Love();}}interface IGentleman {void Love();}interface IKiller {void Kill();}class WarmKiller : IGentleman, IKiller {public void Love() {Console.WriteLine("I will love you for ever..."); }/* 這個方法只有* IKiller類型引用的實例才能夠調用這個方法*/void IKiller.Kill() {throw new NotImplementedException();}}
}

反射

反射不是C#語言的功能,而是.Net框架的功能。

給一個對象,反射能在不適用new操作符,并且也不知道這個對象是什么靜態(tài)類型的情況下,創(chuàng)建出同類型的對象。

還能訪問這個對象所帶有的各個成員。


這就相當于進一步的解耦。因為在有new操作符的地方,一定會跟類型,一旦跟了類型,就有了依賴。而且這種依賴還是緊耦合的?,F(xiàn)在創(chuàng)建對象可以不適用new操作符,可以不出現(xiàn)靜態(tài)類型,那么很多時候這個耦合甚至可弱到忽略不計。


Java開發(fā)體系也有這個機制。

可以說,這是C#和Java這些托管類型語言與c/c++這些原生類型語言最大的區(qū)別之一。

之前學的單元測試,下面要學的依賴注入,還有以后要學的泛型編程,都是基于反射機制的。處于.Net和Java很底層的東西


這么底層的東西,原理一定是很深奧,很復雜。 但是呢,.Net和C#在設計方面十分精妙。一般情況下,我們在使用反射,但是卻感覺不到反射的存在。也就是說,一般不會直接接觸到反射,大部分情況下,都是使用一些已經封裝好了的反射。

很多時候 程序的邏輯,不是我們在寫程序的時候就能夠確定的。有時候,這個邏輯是到了用戶跟程序進行交互的時候,才能確定。這個時候程序已經處在運行狀態(tài)了。
也就是已經處在動態(tài)期了,已經離開開發(fā)和編譯環(huán)境了。如果我們在開發(fā)程序的時候,就枚舉用戶所有能夠進行的操作,那么這個程序就會變得非常難維護。
或者我們不可能考慮到用戶所能進行的所有情況。所以這個時候,程序需要一種 以不變應萬變的能力,這個能力就是反射。

接下來,用兩個例子演示反射的神奇功能:

反射原理

.Net平臺有兩個大的版本:運行在windows上的.Net FramWork和可以擴平臺的.NET Core。兩個平臺都有反射機制,但是類庫不太一樣?,F(xiàn)在使用的是.Net Core程序,以后使用.Net FramWork去做反射的時候,可以去查一下對應的API。

注意,反射是動態(tài)的在內存中進行操作,不要過多的使用反射機制,不然會對程序的性能有所影響。

反射的原理

直接使用反射

using System.Reflection;namespace IspExample4 {/* 背景故事:一個女生開車把車撞了* 她男朋友就哄她說,下次給她買個坦克開*/internal class Program {static void Main(string[] args) {ITank tank = new HeavyTank();//===========分割線===========/* new 后面的HeavyTank就是靜態(tài)類型* GetType()方法可以獲得靜態(tài)類型的一些信息* 比如這個類型包含哪些方法,哪些屬性*/var t = tank.GetType();/* Activator 是激活器* CreateInstance創(chuàng)建t類型的實例,不知道具體的類型* 所以創(chuàng)建的是object類型的*/object o = Activator.CreateInstance(t);//接下來使用反射//獲得t類型的名叫Fire的方法MethodInfo fireMi = t.GetMethod("Fire");MethodInfo runMi = t.GetMethod("run");/* public object? Invoke(object? obj, object?[]? parameters);* 第二個參數(shù)指的是該方法的是否需要傳入一些參數(shù)* 即該方法的參數(shù)列表*/fireMi.Invoke(o, null);runMi.Invoke(o, null);//這里是直接用的反射,但是大部分情況下不會這么用}}class Driver {private IVehicle _vehicle;public Driver(IVehicle vehicle) {_vehicle = vehicle;}public void Drive() {_vehicle.Run();}}interface IVehicle {void Run();}class Car : IVehicle {public void Run() {Console.WriteLine("Car is running...");}}class Truck : IVehicle {public void Run() {Console.WriteLine("Truck is running...");}}interface IWeapon {void Fire();}/* 繼承多個接口* 讓ITank既繼承自IVehicle又繼承自IWeapon*/interface ITank : IVehicle, IWeapon {}class LightTank : ITank {public void Fire() {Console.WriteLine("Boom!");}public void Run() {Console.WriteLine("Ka ka ka...");}}class MediumTank : ITank {public void Fire() {Console.WriteLine("Boom!!");}public void Run() {Console.WriteLine("Ka! ka! ka!...");}}class HeavyTank : ITank {public void Fire() {Console.WriteLine("Boom!!!");}public void Run() {Console.WriteLine("Ka!! ka!! ka!!...");}}
}

依賴注入

(DI – Dependency Injection)縮寫是DI。

依賴反轉原則的縮寫也是DI,Dependency Inversion。

所以此DI非彼DI,但是如果沒有依賴反轉,也就沒有依賴注入。

依賴反轉是一個概念,依賴注入是在這個概念的基礎之上,結合接口和反射機制,所形成的一種應用。

依賴注入最重要的就是有一個容器Container,現(xiàn)在使用的容器是 Microsoft.Extensions.DependencyInjection: 這是.NET Core內置的依賴注入容器,提供了基本的DI功能1。也就是ServiceProvider,把各種各樣的類型和這些類型對應的接口放到容器里面。要實例的時候,就向容器要。注冊類型的時候,還可以指定以后創(chuàng)建對象的時候,是每次創(chuàng)建一個新對象,還是創(chuàng)建一個單例模式,每次都傳同一個實例。這個容器怎么使用,不在這里講,這里主要是看DependencyInjection怎么用。

這篇文章有助于理解依賴注入

[C#]理解和入門依賴注入 - 知乎 (zhihu.com)

依賴注入需要借助依賴注入的框架

在這里插入圖片描述

引入名稱空間

在這里插入圖片描述

using System.Reflection;
using Microsoft.Extensions.DependencyInjection;namespace IspExample4 {internal class Program {static void Main(string[] args) {/* 反射有一種很重要的容器* 叫做container* 這種容器,就不在這里展開了*///服務的提供者var sc = new ServiceCollection();/* typeof()方法用于獲取類型的動態(tài)信息* AddKeyedScoped()方法有很多重載方法,* 我們現(xiàn)在使用的這個* 第一個參數(shù)是基接口* 第二個是誰實現(xiàn)了這個接口* 假如我們沒有使用反射,程序中new 了很多的HeavyTank對象* 當有一天我們需要改成MediumTank的時候,就需要改很多個地方* 而使用了反射,就只需要改成* sc.AddKeyedScoped(typeof(ITank), typeof(MediumTank));* 現(xiàn)在這是基礎用法*/sc.AddScoped(typeof(ITank), typeof(HeavyTank));var sp = sc.BuildServiceProvider();//============分割線==============ITank tank = sp.GetService<ITank>();tank.Fire();tank.Run();//更強大的功能:sc.AddScoped(typeof(IVehicle), typeof(MediumTank));sc.AddScoped<Driver>();var ss = sc.BuildServiceProvider();//===============分割線============var driver = ss.GetService<Driver>();driver.Drive();/* 當typeof()里面是Car的時候,就是調用的Car的Run方法* 當typeof()里面是MediumTank的時候,就是調用的MediumTank的Run方法*/}}class Driver {private IVehicle _vehicle;public Driver(IVehicle vehicle) {_vehicle = vehicle;}public void Drive() {_vehicle.Run();}}interface IVehicle {void Run();}class Car : IVehicle {public void Run() {Console.WriteLine("Car is running...");}}class Truck : IVehicle {public void Run() {Console.WriteLine("Truck is running...");}}interface IWeapon {void Fire();}/* 繼承多個接口* 讓ITank既繼承自IVehicle又繼承自IWeapon*/interface ITank : IVehicle, IWeapon {}class LightTank : ITank {public void Fire() {Console.WriteLine("Boom!");}public void Run() {Console.WriteLine("Ka ka ka...");}}class MediumTank : ITank {public void Fire() {Console.WriteLine("Boom!!");}public void Run() {Console.WriteLine("Ka! ka! ka!...");}}class HeavyTank : ITank {public void Fire() {Console.WriteLine("Boom!!!");}public void Run() {Console.WriteLine("Ka!! ka!! ka!!...");}}
}

反射實現(xiàn)更松的耦合

這種更松的耦合一般使用在插件式編程中。好處是,以主體程序為中心,生成一個生態(tài)圈,在這個生態(tài)圈中,不斷的更新主體程序,于是就有人不斷用插件往上面添加新功能并且從中獲利。微軟的很多東西都是帶有這種生態(tài)圈的。


插件,不與主體程序一起編譯,但是與主體程序一起工作,往往由第三方提供。

主體程序和插件的關系,就是不變和萬變的關系。

主體程序會發(fā)布包含有程序開發(fā)接口、API(Application Programming Interface)程序開發(fā)包,就是SDK(Software Development Kit)


反射開發(fā)會太自由了,發(fā)布API可以約束開發(fā)者開發(fā)第三方插件,同時也減輕開發(fā)者的一些勞動。

背景:作為嬰兒車的廠商,要發(fā)明一種帶面板的嬰兒車。

這種面板有兩排按鈕,第一排按鈕是一些小動物的頭像,第二排按鈕是一些數(shù)字,按下小動物,再按下數(shù)字,就會發(fā)出對應次數(shù)的叫聲。

然后我們設計一個接口,可以讓第三方,自己定義動物的種類,自己定義次數(shù),只需要一個USB接口就可以傳進去。

純反射

這是指,不依賴于任何預先定義的接口或基類,而是完全通過反射來檢查和操作程序集、類型、成員等。這種方式可以在運行時動態(tài)地創(chuàng)建對象、調用方法、訪問字段和屬性,甚至修改類型的行為。

主體程序:

using System.IO;
using System.Reflection;
using System.Runtime.Loader;
namespace BabyStroller.App {internal class Program {/* 主體程序會將Animals文件夾中* 第三方提供的插件加載進來* 去調用里面所有小動物的Voice(int num)方法* * 在主體程序中主要寫:* 利用反射加載插件,拿到這些動物類,然后創(chuàng)建實例* 并且調用實例的Voice方法* 這樣的功能*/static void Main(string[] args) {Console.WriteLine(Environment.CurrentDirectory);//查看當前項目所處文件夾,創(chuàng)建Animals文件夾var folder = Path.Combine(Environment.CurrentDirectory, "Animals");var files = Directory.GetFiles(folder);var animalTypes = new List<Type>();foreach ( var file in files) {var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);var types = assembly.GetTypes();//得到加載進來的類型foreach ( var type in types) {//將含有Voice方法的類型加入到List中if (type.GetMethod("Voice") != null){animalTypes.Add(type);}}}/* 開始運行游戲* 很多這種面板里面實際上就是個死循環(huán),* 除非強制關機、或者電池沒電,* 不然會一直轉下去,或者程序崩潰*/while (true) {//先打印有多少種動物for ( int i = 0; i < animalTypes.Count; i++ ) {Console.WriteLine($"{i + 1}.{animalTypes[i].Name}");}Console.WriteLine("=======================================");//選擇動物Console.WriteLine("Please choose animal:");int index = int.Parse( Console.ReadLine() );if( index > animalTypes.Count || index < 1 ) {Console.WriteLine("No such an animal.Try again!");continue;}//選擇次數(shù)Console.WriteLine("How many times?");int times = int.Parse( Console.ReadLine() );var t = animalTypes[index - 1];var m = t.GetMethod("Voice");//調用無參構造器實例化的對象var o = Activator.CreateInstance(t);//調用該方法,并傳入?yún)?shù)列表數(shù)組m.Invoke(o, new object[] { times });}}}
}

第三方提供的類

分別有兩個類庫,一共四個類,為了演示效果,沒有做太多的類。

在這里插入圖片描述

在這里插入圖片描述

然后將第三方寫的類庫,生成

再將兩個類庫生成的.dll文件添加到主體程序所在文件夾中的Animals文件夾中

在這里插入圖片描述

在這里插入圖片描述

于是就可以成功運行主體程序了。

在這里插入圖片描述

使用接口的反射

創(chuàng)建一個接口或抽象類來定義操作的契約,然后通過反射動態(tài)地加載和實例化實現(xiàn)了這些接口或抽象類的具體類。

使用純反射,很容易犯錯誤,比如把方法名字寫錯了,那么這個類就會被看不到了。

為了避免第三方,開發(fā)犯錯誤,以及減少開發(fā)成本。

首先制作接口文件:

在這里插入圖片描述

Attribute類用于保護那些未寫完的動物類

在這里插入圖片描述

然后將這個接口項目生成.dll文件。

接著,在第三方中,添加并使用主體程序發(fā)布的接口

在這里插入圖片描述

然后修改部分代碼:

在這里插入圖片描述

在這里插入圖片描述

接著,讓這兩個類庫生成.dll文件

接把新build.dll文件,再次放到主程序所在的Animals文件夾中,將原來的覆蓋掉

然后修改主程序

using BabyStroller.SDK;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
namespace BabyStroller.App {internal class Program {/* 主體程序會將Animals文件夾中* 第三方提供的插件加載進來* 去調用里面所有小動物的Voice(int num)方法* * 在主體程序中主要寫:* 利用反射加載插件,拿到這些動物類,然后創(chuàng)建實例* 并且調用實例的Voice方法* 這樣的功能*/static void Main(string[] args) {Console.WriteLine(Environment.CurrentDirectory);//查看當前項目所處文件夾,創(chuàng)建Animals文件夾var folder = Path.Combine(Environment.CurrentDirectory, "Animals");var files = Directory.GetFiles(folder);var animalTypes = new List<Type>();foreach ( var file in files) {//遍歷文件//得到一個程序集var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);//得到程序集中的類型集合var types = assembly.GetTypes();//得到加載進來的類型foreach ( var t in types) {//遍歷這個類型集合//將含有Voice方法的類型加入到List中//if (t.GetMethod("Voice") != null){//    animalTypes.Add(t);//}//有了SDK,后就不用這種笨的辦法了/* 現(xiàn)在只需要判斷一下,* 這個類型是不是IAnimal接口的實現(xiàn)類型* 并且沒有被[UnFinishedAttribute]這個特性所修飾*/if(t.GetInterfaces().Contains(typeof(IAnimal))){var isUnfinished  = t.GetCustomAttributes(false).Any(a =>a.GetType() == typeof(UnfinishedAttribute));animalTypes.Add(t);}}}/* 開始運行游戲* 很多這種面板里面實際上就是個死循環(huán),* 除非強制關機、或者電池沒電,* 不然會一直轉下去,或者程序崩潰*/while (true) {//先打印有多少種動物for ( int i = 0; i < animalTypes.Count; i++ ) {Console.WriteLine($"{i + 1}.{animalTypes[i].Name}");} Console.WriteLine("=======================================");//選擇動物Console.WriteLine("Please choose animal:");int index = int.Parse( Console.ReadLine() );if( index > animalTypes.Count || index < 1 ) {Console.WriteLine("No such an animal.Try again!");continue;}//選擇次數(shù)Console.WriteLine("How many times?");int times = int.Parse( Console.ReadLine() );var t = animalTypes[index - 1];var m = t.GetMethod("Voice");//調用無參構造器實例化的對象var o = Activator.CreateInstance(t);//調用該方法,并傳入?yún)?shù)列表數(shù)組//m.Invoke(o, new object[] { times });var a = o as IAnimal;a.Voice(times);}}}
}

特性

其作用就是在使用反射的時候,通過反射拿到一個方法或一個類看有沒有被某個Attribute所修飾,然后再做決定,是否調用,是否保留等等。這就是Attribute的用處。

之前單元測試中的帶框的英文就是Attribute

可以看看這篇文章

【Unity】Unity C#基礎(十二)特性Attribute、反射Reflection_unity attributeusage-CSDN博客

補充

Activator是一個用于快速實例化對象的類。比如:用于將Type信息類對象快速實例化為對象。通過反射來實例化。

Type的一些用法

using System.Reflection;
using System.Runtime.CompilerServices;namespace AllReflectionExample {class Test {private int i = 1;public int j = 0;public string str = "Hello";public Test(){}public Test(int i) {this.i = i;}//對構造器的重載public Test(int i, string str): this(i){this.str = str;}public void Speak() {Console.WriteLine(i);}}internal class Program {static void Main(string[] args) {//Type 是類的信息類#region 獲取Type的方式// 1.object中的GetType()方法可以獲得Typeint num = 5;Type t = num.GetType();Console.WriteLine(t);// 2.通過typeof關鍵字 傳入類名Type t2 = typeof(int);Console.WriteLine(t2);// 3.通過類的名字 不過必須得是包含名稱空間的全稱,不然找不到Type t3 = Type.GetType("System.Int32");Console.WriteLine(t3);#endregion#region 獲取類中的所有公共成員//先得到信息類Type t4 = typeof(Test);//得到公共成員,需要引用命名空間using System.Reflection;MemberInfo[] infos = t4.GetMembers();for (int i = 0; i < infos.Length; i++) {Console.WriteLine(infos[i]);}#endregion#region 獲取類的公共構造函數(shù)并調用//1.獲取所有構造函數(shù)ConstructorInfo[] ctors = t.GetConstructors();for (int i = 0; i < ctors.Length; i++) { Console.WriteLine(ctors[i]);}//2.獲取其中一個構造函數(shù) 并執(zhí)行//得構造函數(shù)傳入 Type數(shù)組 數(shù)組中內容按順序是參數(shù)類型//執(zhí)行構造函數(shù)傳入 object數(shù)組 表示按順序傳入的參數(shù)//2 - 1得到無參構造ConstructorInfo info = t.GetConstructor(new Type[0]);//執(zhí)行無參構造函數(shù) 沒有參數(shù) 傳nullTest obj = info.Invoke(null) as Test;Console.WriteLine(obj.j);//2 - 2得到有參構造ConstructorInfo info2 = t.GetConstructor(new Type[] {typeof(int)});obj = info2.Invoke(new object[] {2}) as Test;Console.WriteLine(obj.str);ConstructorInfo info3 = t.GetConstructor(new Type[] { typeof(int), typeof(string) });obj = info3.Invoke(new object[] { 4, "shaoi"}) as Test;Console.WriteLine(obj.str);#endregion//還可以通過這種方式,獲取類的公共其他成員并調用}}
}

Assembly

程序集類,主要用來加載其他程序集,加載后才能用type來使用其他程序集中的信息。

如果想要使用不是自己程序集中的內容,就需要先加載該程序集,比如dll庫文件。

如果想要詳細了解,可以去看其他文章,這里僅做介紹。

在這里,我想說一下,知識是學不完的,但是當我們學到某種程度就足夠我們使用了。

如果以后再遇到需要再深入學習,到那個時候,可以再學。

http://www.risenshineclean.com/news/11436.html

相關文章:

  • 集團做網站方案制作包含哪些方面如何制作自己的鏈接
  • wordpress 調用分類目錄描述金華seo扣費
  • 一個網站按鈕怎么做圖片優(yōu)化
  • 網站優(yōu)化工作怎么樣seo和點擊付費的區(qū)別
  • 可以做皮膚測試的網站關鍵詞排名優(yōu)化如何
  • 網站建設找蓋亞科技營銷網站模板
  • 證件照制作免費版優(yōu)化網站seo策略
  • 如何提高網站點擊率怎么做合肥百度seo代理
  • 中國建設銀行余額查詢入口seo推廣人員
  • 網站在香港能備案嗎沈陽seo關鍵詞
  • 杭州品牌網站開發(fā)東莞網站推廣的公司
  • 2018做論壇網站好嗎百度推廣工作好干嗎
  • 網站制作公司排行榜建設網站
  • 營銷型網站開發(fā)泰安網站制作推廣
  • 網站建設制作設計推廣優(yōu)化國產十大erp軟件
  • 記賬代理公司注冊網絡seo優(yōu)化推廣
  • 昌吉網站建設哪家便宜seo站外優(yōu)化平臺
  • java php開發(fā)網站建設收錄入口在線提交
  • 公司網站建設技術方案模板免費創(chuàng)建個人網頁
  • 響應式手機網站制作西安seo顧問
  • 微信建立免費網站嗎360優(yōu)化大師官網
  • apache和wordpress網站seo關鍵詞優(yōu)化排名
  • 網站開發(fā)商ui設計培訓班哪家好
  • 網站建設的方法免費快速網站
  • 平衡木網站建設搜索網站排行榜
  • 個人網站可以做社交類型網絡營銷案例題
  • 東莞免費做網站今天有哪些新聞
  • 外貿公司的經營范圍鄭州seo網絡推廣
  • 銀川網站建設哪家好手機優(yōu)化大師下載安裝
  • 未滿18歲能申請網站備案嗎網站模板之家