C# 依賴注入框架Grace的使用

C# 依賴注入框架Grace

Grace是一個我偶爾刷技術博客的時候才知道的依賴注入框架,根據項目的github瞭解到,Grace是一個開源、輕巧、易用同時特性豐富、性能優秀的依賴注入容器框架。

Grace is a feature-rich dependency injection container designed with ease of use and performance in mind.

比較令人詫異的是,Grace的作者Ian Johnson,幾乎沒有寫任何文檔,而且用法也找不到任何中文資料,哪怕是英文的使用文檔和教程也是很少,我試圖從stack overflow上找,也是寥寥無幾的問題,最後我還是從作者的Github項目主頁的Issues中找到了使用的蛛絲馬跡,居然是從作者的單元測試中找用法Demo。簡直厲害了。

1. 項目鏈接

Nuget:https://www.nuget.org/packages/Grace/

Github:https://github.com/ipjohnson/Grace

測評鏈接 IoC Container Benchmark - Performance comparison

2. 倉儲類Demo設計

按照作者給出的Demo,稍加改造一下,Ian Johnson設計了賬戶/用戶/服務三個接口倉儲類作爲Demo的演示用例,我在這裏列出一下。

/// <summary>
/// 賬戶倉儲接口
/// </summary>
public interface IAccountRepository
{
	string Get();
}
/// <summary>
/// 賬戶倉儲類
/// </summary>
public class AccountRepository : IAccountRepository
{
	public string Get()
	{
		return "[AccountRepository] 簡單註冊調用";
	}
}
/// <summary>
/// 賬戶服務接口
/// </summary>
public interface IAccountService
{
	string Get();
}
/// <summary>
/// 賬戶服務類
/// </summary>
public class AccountService : IAccountService
{
	IAccountRepository _accountRepository;
	public AccountService(IAccountRepository accountRepository)
	{
		_accountRepository = accountRepository;
	}

	public string Get()
	{
		return _accountRepository.Get() + " [AccountService] ";
	}
}
/// <summary>
/// 用戶倉儲接口
/// </summary>
public interface IUserRepository
{
	string Get();
}
/// <summary>
/// 用戶倉儲A類
/// </summary>
public class UserRepositoryA : IUserRepository
{
	public string Get()
	{
		return "[UserRepositoryA] 鍵值註冊調用 ";
	}
}
/// <summary>
/// 用戶倉儲B類
/// </summary>
public class UserRepositoryB : IUserRepository
{
	public UserRepositoryB(string param1, string param2)
	{
		Console.WriteLine($"Ctor param1:{param1} {param2}");
	}

	public string Get()
	{
		return "[UserRepositoryB] 鍵值註冊調用 ";
	}
}
/// <summary>
/// 用戶服務接口
/// </summary>
public interface IUserService
{
	string Get();
}
/// <summary>
/// 用戶服務類
/// </summary>
public class UserService : IUserService
{
	IUserRepository _userRepository;
	public UserService(IUserRepository userRepository)
	{
		_userRepository = userRepository;
	}

	public string Get()
	{
		return _userRepository.Get() + " [UserService] ";
	}
}

3. 注入實例演示

Grace框架注入操作也和其他的IoC一樣,也是先聲明一個容器,再按照幾個特定的模式進行相應的注入,這裏有點不明白的是,爲何UserRepositoryB的構造參數有兩個,但是注入的時候給的參數只有一個,但實例接收到的卻依然是兩個參數,一模一樣的參數,等於複製了兩份,如果有大神看懂了其中的奧妙,幫忙告訴我一下哈,十分感謝!

//容器
var container = new DependencyInjectionContainer();

container.Configure(m =>
{
	//這裏演示如何簡單註冊同一個接口對應其實現
	m.Export<AccountRepository>().As<IAccountRepository>();
	m.Export<AccountService>().As<IAccountService>();

	//這裏演示如何使用鍵值以單例的模式註冊同一個接口的多個實現
	m.Export<UserRepositoryA>().AsKeyed<IUserRepository>("A").Lifestyle.Singleton();
	//這裏同時演示使用帶參數構造器來鍵值註冊
	m.Export<UserRepositoryB>().AsKeyed<IUserRepository>("B").WithCtorParam<string>(
		() => {
			return "paramA";
			}
		);
	//這裏演示依賴倒置而使用構造器帶鍵值注入
	m.Export<UserService>().As<IUserService>().WithCtorParam<IUserRepository>().LocateWithKey("B");

});

4. 使用實例演示

使用也很簡潔明瞭,用容器對象和註冊類型定位一下就可以,關於生命週期,Grace框架裏提供了幾種,還可以自行擴展,這點比較強大。給定的幾種模式分別是 Singleton, SingletonPerScope, SingletonPerRequest , SingletonPerObjectGraph, SingletonPerAncestor, and WeakSingleton,這幾個模式的從英文意思上大概可以猜出來,但是大神 Ian Johnson 沒有給出來文檔和Demo,估計大神是想讓我們看他的源碼自己意會,也可能是大神覺得很簡單,簡單到不用直接說明。。。。

Many LifeStyles supported including Singleton, SingletonPerScope, SingletonPerRequest (MVC4, MVC5 & WCF packages), SingletonPerObjectGraph, SingletonPerAncestor, and WeakSingleton. If none of the provided life styles meet your need you can always implement your own ICompiledLifeStyle class.

//獲取簡單註冊實例
var accountRepo = container.Locate<IAccountRepository>();
Console.WriteLine(accountRepo.Get());
// [AccountRepository] 簡單註冊調用

var accountSvc = container.Locate<IAccountService>();
Console.WriteLine(accountSvc.Get());
// [AccountRepository] 簡單註冊調用 [AccountService]

Console.WriteLine();

//獲取指定鍵值的實例
var userRepo1 = container.Locate<IUserRepository>(withKey: "A");
var userRepo2 = container.Locate<IUserRepository>(withKey: "A");

// 判斷單例兩個對象是否相等
bool isEqual = userRepo1.Equals(userRepo2);
Console.WriteLine(isEqual); // True

Console.WriteLine(userRepo1.Get());
// [UserRepositoryA] 鍵值註冊調用

var userRepoB = container.Locate<IUserRepository>(withKey: "B");
Console.WriteLine(userRepoB.Get());
// Ctor param: paramA paramA
// [UserRepositoryB] 鍵值註冊調用

Console.Read();

5. 難點存疑

1、 不太清楚多個構造函數的實例怎麼注入,暫時沒找到Demo,可能得擼代碼。
2、各種生命週期的實例還沒有深入理解。

6. 相關博客鏈接

C#下IOC/依賴注入框架Grace介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章