C\#의 의존 주입 과 IoC 용기 에 대한 자세 한 설명
프로필:
주입 과 IoC 에 의존 하 는 것 은 언뜻 보기 에는 상당히 복잡 할 수 있 지만 쉽게 배우 고 이해 할 수 있다.
본 논문 에서 우 리 는 C\#에서 매우 간단 한 코드 예 시 를 재 구성 하여 주입 과 IoC 용기 에 의존 하 는 것 을 설명 할 것 이다.
요청:
사용 가능 한 제품 을 보고 이름 에 따라 제품 을 검색 할 수 있 는 프로그램 을 만 듭 니 다.
첫 번 째 시도:
우 리 는 층 구 조 를 만 드 는 것 부터 시작 할 것 이다.분 층 구 조 를 사용 하 는 것 은 여러 가지 장점 이 있 지만 우 리 는 본 논문 에서 그것들 을 열거 하지 않 을 것 이다.왜냐하면 우리 가 주목 하 는 것 은 주입 에 의존 하 는 것 이기 때문이다.
다음은 응용 프로그램의 클래스 입 니 다.
우선,우 리 는 Product 클래스 를 만 드 는 것 부터 시작 할 것 입 니 다.
public class Product
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
그리고 데이터 액세스 층 을 만 들 것 입 니 다:
public class ProductDAL
{
private readonly List<Product> _products;
public ProductDAL()
{
_products = new List<Product>
{
new Product { Id = Guid.NewGuid(), Name= "iPhone 9",
Description = "iPhone 9 mobile phone" },
new Product { Id = Guid.NewGuid(), Name= "iPhone X",
Description = "iPhone X mobile phone" }
};
}
public IEnumerable<Product> GetProducts()
{
return _products;
}
public IEnumerable<Product> GetProducts(string name)
{
return _products
.Where(p => p.Name.Contains(name))
.ToList();
}
}
그리고 우 리 는 업무 층 을 만 들 것 입 니 다.
public class ProductBL
{
private readonly ProductDAL _productDAL;
public ProductBL()
{
_productDAL = new ProductDAL();
}
public IEnumerable<Product> GetProducts()
{
return _productDAL.GetProducts();
}
public IEnumerable<Product> GetProducts(string name)
{
return _productDAL.GetProducts(name);
}
}
마지막 으로 UI 를 만 들 것 입 니 다:
class Program
{
static void Main(string[] args)
{
ProductBL productBL = new ProductBL();
var products = productBL.GetProducts();
foreach (var product in products)
{
Console.WriteLine(product.Name);
}
Console.ReadKey();
}
}
우리 가 처음 시도 한 코드 는 좋 은 작업 성과 라 고 썼 지만 몇 가지 문제 가 있다.1.우 리 는 세 개의 서로 다른 팀 을 각 층 에서 일 하 게 해 서 는 안 된다.
2.업무 층 은 데이터 액세스 층 의 실현 에 의존 하기 때문에 확장 하기 어렵다.
3.업무 층 은 데이터 액세스 층 의 실현 에 의존 하기 때문에 유지 하기 어렵다.
4.소스 코드 는 테스트 하기 어렵다.
두 번 째 시도:
높 은 등급 의 대상 은 낮은 등급 의 대상 에 의존 해 서 는 안 된다.둘 다 추상 에 의존 해 야 한다.그렇다면 추상 적 인 개념 은 무엇 일 까?
추상 은 기능 의 정의 이다.우리 의 예 에서 업무 층 은 데이터 액세스 층 에 의존 하여 도 서 를 검색 한다.C\#에서 우 리 는 인 터 페 이 스 를 사용 하여 추상 을 실현 한다.인 터 페 이 스 는 기능 의 추상 을 나타 낸다.
추상 을 만들어 봅 시다.
다음은 데이터 액세스 층 의 추상 입 니 다.
public interface IProductDAL
{
IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProducts(string name);
}
데이터 액세스 층 을 업데이트 해 야 합 니 다.
public class ProductDAL : IProductDAL
우 리 는 업무 층 을 갱신 해 야 한다.실제로 저 희 는 업무 층 을 업데이트 하여 데이터 액세스 층 의 추상 에 의존 하 게 할 것 입 니 다.데이터 액세스 층 의 실현 에 의존 하 는 것 이 아 닙 니 다.
public class ProductBL
{
private readonly IProductDAL _productDAL;
public ProductBL()
{
_productDAL = new ProductDAL();
}
public IEnumerable<Product> GetProducts()
{
return _productDAL.GetProducts();
}
public IEnumerable<Product> GetProducts(string name)
{
return _productDAL.GetProducts(name);
}
}
우 리 는 또한 업무 층 의 추상 을 만들어 야 한다.
public interface IProductBL
{
IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProducts(string name);
}
우리 도 업무 층 을 갱신 해 야 한다.
public class ProductBL : IProductBL
최종 적 으로 UI 를 업데이트 해 야 합 니 다:
class Program
{
static void Main(string[] args)
{
IProductBL productBL = new ProductBL();
var products = productBL.GetProducts();
foreach (var product in products)
{
Console.WriteLine(product.Name);
}
Console.ReadKey();
}
}
우리 가 두 번 째 시도 에서 한 코드 는 유효 하지만,우 리 는 여전히 데이터 액세스 층 의 구체 적 인 실현 에 의존한다.
public ProductBL()
{
_productDAL = new ProductDAL();
}
그렇다면 어떻게 해결 할 것 인가?주입 패턴 에 의존 해 역할 을 하 는 곳 이다.
최종 시도
지금까지 우리 가 한 일 은 주입 에 의존 하 는 것 과 무관 하 다.
높 은 등급 에 있 는 업무 층 을 낮은 등급 의 대상 에 의존 하 게 하기 위해 서 는 구체 적 으로 실현 되 지 않 고 다른 사람 이 클래스 를 만들어 야 한다.다른 사람들 은 반드시 밑바닥 대상 의 구체 적 인 실현 을 제공 해 야 한다.이것 이 바로 우리 가 말 한 의존 주입 이다.그것 은 우리 가 의존 대상 을 더 높 은 등급 의 대상 에 주입 한 다 는 뜻 이다.의존 항 주입 을 실현 하 는 방법 중 하 나 는 구조 함 수 를 사용 하여 의존 항 주입 을 하 는 것 이다.
업무 층 업데이트:
public class ProductBL : IProductBL
{
private readonly IProductDAL _productDAL;
public ProductBL(IProductDAL productDAL)
{
_productDAL = productDAL;
}
public IEnumerable<Product> GetProducts()
{
return _productDAL.GetProducts();
}
public IEnumerable<Product> GetProducts(string name)
{
return _productDAL.GetProducts(name);
}
}
인 프 라 시설 은 반드시 실현 에 대한 의존 을 제공 해 야 한다.
class Program
{
static void Main(string[] args)
{
IProductBL productBL = new ProductBL(new ProductDAL());
var products = productBL.GetProducts();
foreach (var product in products)
{
Console.WriteLine(product.Name);
}
Console.ReadKey();
}
}
데이터 액세스 층 을 만 드 는 제어 와 인 프 라 를 결합 합 니 다.반전 을 통제 하 는 것 이 라 고도 한다.우 리 는 업무 층 에서 데이터 액세스 층 을 만 드 는 실례 가 아니 라 인 프 라 시설 에서 만 듭 니 다. Main 방법 은 인 스 턴 스 를 업무 논리 층 에 주입 합 니 다.따라서 우 리 는 저층 대상 의 실례 를 고위 층 대상 의 실례 에 주입 한다.의존 주입 이 라 고 합 니 다.
지금 우리 가 코드 를 보면 우 리 는 업무 액세스 층 에서 데이터 액세스 층 의 추상 에 만 의존 하고 업무 액세스 층 은 데이터 액세스 층 이 실현 하 는 인 터 페 이 스 를 사용한다.따라서 우 리 는 더욱 높 은 차원 의 대상 과 더 낮은 차원 의 대상 이 모두 추상 적 인 원칙 에 의존 하고 추상 은 더욱 높 은 차원 의 대상 과 더 낮은 차원 의 대상 간 의 계약 이다.
이제 우 리 는 서로 다른 팀 을 서로 다른 층 에서 일 하 게 할 수 있다.우 리 는 한 팀 이 데이터 액세스 층 을 처리 하고 한 팀 이 업무 층 을 처리 하 며 한 팀 이 UI 를 처리 하도록 할 수 있다.
다음은 유지 가능성 과 확장 가능 한 장점 을 보 여 줍 니 다.예 를 들 어 SQL Server 에 새로운 데이터 액세스 층 을 만 들 려 면 데이터 액세스 층 의 추상 화 를 실현 하고 인 프 라 에 인 스 턴 스 를 주입 해 야 합 니 다.
마지막 으로 소스 코드 는 이제 테스트 할 수 있 습 니 다.우 리 는 어느 곳 에서 든 인 터 페 이 스 를 사용 하기 때문에 비교적 낮은 단원 테스트 에서 다른 실현 을 쉽게 제공 할 수 있다.낮은 테스트 가 쉽게 설 치 될 것 이라는 뜻 이다.
이제 업무 층 을 테스트 합 시다.
저 희 는 xUnit 을 사용 하여 유닛 테스트 를 하고 Moq 아 날로 그 데이터 액세스 층 을 사용 할 것 입 니 다.
다음은 업무 층 의 유닛 테스트 입 니 다.
public class ProductBLTest
{
private readonly List<Product> _products = new List<Product>
{
new Product { Id = Guid.NewGuid(), Name= "iPhone 9",
Description = "iPhone 9 mobile phone" },
new Product { Id = Guid.NewGuid(), Name= "iPhone X",
Description = "iPhone X mobile phone" }
};
private readonly ProductBL _productBL;
public ProductBLTest()
{
var mockProductDAL = new Mock<IProductDAL>();
mockProductDAL
.Setup(dal => dal.GetProducts())
.Returns(_products);
mockProductDAL
.Setup(dal => dal.GetProducts(It.IsAny<string>()))
.Returns<string>(name => _products.Where(p => p.Name.Contains(name)).ToList());
_productBL = new ProductBL(mockProductDAL.Object);
}
[Fact]
public void GetProductsTest()
{
var products = _productBL.GetProducts();
Assert.Equal(2, products.Count());
}
[Fact]
public void SearchProductsTest()
{
var products = _productBL.GetProducts("X");
Assert.Single(products);
}
}
의존 항 주입 을 사용 하면 유닛 테스트 를 쉽게 설정 할 수 있 음 을 볼 수 있 습 니 다.IoC 용기
용 기 는 주입 에 의존 하 는 것 을 실현 하 는 데 도움 을 줄 뿐이다.용 기 는 보통 세 가지 서로 다른 기능 을 실현 한다.
1.등록 인터페이스 와 구체 적 인 실현 사이 의 맵
2.대상 을 만 들 고 의존 관 계 를 분석
3.석방
맵 을 등록 하고 대상 을 만 드 는 간단 한 용 기 를 실현 합 니 다.
우선,우 리 는 매 핑 된 데이터 구 조 를 저장 해 야 한다.우 리 는 Hashtable 을 선택 할 것 이다.이 데이터 구 조 는 매 핑 을 저장 할 것 이다.
우선,우 리 는 용기 의 구조 함수 에서 Hashtable 을 초기 화 할 것 입 니 다.그리고 나 서,우 리 는 등록 맵 을 등록 하기 위해 RegisterTransient 방법 을 만 들 것 이다.마지막 으로 대상 을 만 드 는 방법 을 만 들 것 입 니 다. Create :
public class Container
{
private readonly Hashtable _registrations;
public Container()
{
_registrations = new Hashtable();
}
public void RegisterTransient<TInterface, TImplementation>()
{
_registrations.Add(typeof(TInterface), typeof(TImplementation));
}
public TInterface Create<TInterface>()
{
var typeOfImpl = (Type)_registrations[typeof(TInterface)];
if (typeOfImpl == null)
{
throw new ApplicationException($"Failed to resolve {typeof(TInterface).Name}");
}
return (TInterface)Activator.CreateInstance(typeOfImpl);
}
}
최종 적 으로 UI 를 업데이트 합 니 다.
class Program
{
static void Main(string[] args)
{
var container = new Container();
container.RegisterTransient<IProductDAL, ProductDAL>();
IProductBL productBL = new ProductBL(container.Create<IProductDAL>());
var products = productBL.GetProducts();
foreach (var product in products)
{
Console.WriteLine(product.Name);
}
Console.ReadKey();
}
}
이제 용기 에서 Resolve 방법 을 실현 합 니 다.이 방법 은 의존 관 계 를 해결 할 것 이다.Resolve 방법 은 다음 과 같 습 니 다.
public T Resolve<T>()
{
var ctor = ((Type)_registrations[typeof(T)]).GetConstructors()[0];
var dep = ctor.GetParameters()[0].ParameterType;
var mi = typeof(Container).GetMethod("Create");
var gm = mi.MakeGenericMethod(dep);
return (T)ctor.Invoke(new object[] { gm.Invoke(this, null) });
}
그리고 우 리 는 UI 에서 다음 과 같은 Resolve 방법 을 사용 할 수 있 습 니 다.
class Program
{
static void Main(string[] args)
{
var container = new Container();
container.RegisterTransient<IProductDAL, ProductDAL>();
container.RegisterTransient<IProductBL, ProductBL>();
var productBL = container.Resolve<IProductBL>();
var products = productBL.GetProducts();
foreach (var product in products)
{
Console.WriteLine(product.Name);
}
Console.ReadKey();
}
}
위의 소스 코드 에서 용 기 는 container.Resolve이것 은 당신 에 게 IoC 용기 뒤의 내용 을 보 여 주 는 매우 간단 하고 기본 적 인 IoC 용기 입 니 다.그렇습니다.나 는 네가 이 문장 을 즐겨 읽 기 를 바란다.
이상 은 C\#의 의존 주입 과 IoC 용기 에 대한 상세 한 내용 입 니 다.C\#의존 주입 과 IoC 용기 에 대한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.