C #의 유창한 인터페이스 및 상속
예를 들어 문제를 보여 드리겠습니다. 유창한 인터페이스를 가진 기본 클래스가 있습니다.
class FluentPerson
{
private string _FirstName = String.Empty;
private string _LastName = String.Empty;
public FluentPerson WithFirstName(string firstName)
{
_FirstName = firstName;
return this;
}
public FluentPerson WithLastName(string lastName)
{
_LastName = lastName;
return this;
}
public override string ToString()
{
return String.Format("First name: {0} last name: {1}", _FirstName, _LastName);
}
}
및 자식 클래스 :
class FluentCustomer : FluentPerson
{
private long _Id;
private string _AccountNumber = String.Empty;
public FluentCustomer WithAccountNumber(string accountNumber)
{
_AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(long id)
{
_Id = id;
return this;
}
public override string ToString()
{
return base.ToString() + String.Format(" account number: {0} id: {1}", _AccountNumber, _Id);
}
}
문제는 메서드 의 반환 유형 이 FluentCustomer가 아닌 FluentPerson 이기 때문에 호출 customer.WithAccountNumber("000").WithFirstName("John").WithLastName("Smith")
할 때 .WithId(123)
끝에 추가 할 수 없다는 것 WithLastName()
입니다.
이 문제는 일반적으로 어떻게 해결됩니까?
제네릭을 사용하여이를 달성 할 수 있습니다.
public class FluentPerson<T>
where T : FluentPerson<T>
{
public T WithFirstName(string firstName)
{
// ...
return (T)this;
}
public T WithLastName(string lastName)
{
// ...
return (T)this;
}
}
public class FluentCustomer : FluentPerson<FluentCustomer>
{
public FluentCustomer WithAccountNumber(string accountNumber)
{
// ...
return this;
}
}
그리고 지금:
var customer = new FluentCustomer()
.WithAccountNumber("123")
.WithFirstName("Abc")
.WithLastName("Def")
.ToString();
일부 확장 방법을 사용해보십시오.
static class FluentManager
{
public static T WithFirstName<T>(this T person, string firstName) where T : FluentPerson
{
person.FirstName = firstName;
return person;
}
public static T WithId<T>(this T customer, long id) where T : FluentCustomer
{
customer.ID = id;
return customer;
}
}
class FluentPerson
{
public string FirstName { private get; set; }
public string LastName { private get; set; }
public override string ToString()
{
return string.Format("First name: {0} last name: {1}", FirstName, LastName);
}
}
class FluentCustomer : FluentPerson
{
public long ID { private get; set; }
public long AccountNumber { private get; set; }
public override string ToString()
{
return base.ToString() + string.Format(" account number: {0} id: {1}", AccountNumber, ID);
}
}
다음과 같이 사용할 수 있습니다.
new FluentCustomer().WithId(22).WithFirstName("dfd").WithId(32);
논리적으로 가장 구체적인 (고객)에서 가장 구체적인 (사람)으로 구성해야합니다. 그렇지 않으면 유창한 인터페이스에도 불구하고 읽기가 어렵습니다. 대부분의 경우이 규칙을 따르면 문제가 발생하지 않습니다. 그러나 어떤 이유로 든 혼합해야하는 경우 다음과 같은 중간 강조 문구를 사용할 수 있습니다.
static class Customers
{
public static Customer AsCustomer(this Person person)
{
return (Customer)person;
}
}
customer.WIthLastName("Bob").AsCustomer().WithId(10);
유창한 인터페이스, 상속 및 일부 제네릭이 필요한 솔루션 ...
어쨌든 이전에 언급했듯이 상속을 사용하고 보호 된 구성원에 액세스하려는 경우 유일한 옵션입니다 ...
public class GridEx<TC, T> where TC : GridEx<TC, T> { public TC Build(T type) { return (TC) this; } } public class GridExEx : GridEx<GridExEx, int> { } class Program { static void Main(string[] args) { new GridExEx().Build(1); } }
public class FluentPerson
{
private string _FirstName = String.Empty;
private string _LastName = String.Empty;
public FluentPerson WithFirstName(string firstName)
{
_FirstName = firstName;
return this;
}
public FluentPerson WithLastName(string lastName)
{
_LastName = lastName;
return this;
}
public override string ToString()
{
return String.Format("First name: {0} last name: {1}", _FirstName, _LastName);
}
}
public class FluentCustomer
{
private string _AccountNumber = String.Empty;
private string _id = String.Empty;
FluentPerson objPers=new FluentPerson();
public FluentCustomer WithAccountNumber(string accountNumber)
{
_AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(string id)
{
_id = id;
return this;
}
public FluentCustomer WithFirstName(string firstName)
{
objPers.WithFirstName(firstName);
return this;
}
public FluentCustomer WithLastName(string lastName)
{
objPers.WithLastName(lastName);
return this;
}
public override string ToString()
{
return objPers.ToString() + String.Format(" account number: {0}", _AccountNumber);
}
}
그리고
var ss = new FluentCustomer().WithAccountNumber("111").WithFirstName("ram").WithLastName("v").WithId("444").ToString();
유창한 인터페이스가 실제로 가장 좋은 호출입니까? 아니면 이니셜 라이저가 더 좋을까요?
var p = new Person{
LastName = "Smith",
FirstName = "John"
};
var c = new Customer{
LastName = "Smith",
FirstName = "John",
AccountNumber = "000",
ID = "123"
};
유창한 인터페이스와 달리 이것은 상속 된 메서드가 기본 클래스를 반환하고 체인을 엉망으로 만들지 않고도 잘 작동합니다. 속성을 상속 할 때 호출자는 실제로 FirstName
Person, Customer 또는 Object에서 처음 구현 되었는지 신경 쓰지 않아야합니다 .
나는 한 줄 또는 여러에 대한 여부,뿐만 아니라이 더 읽기 발견, 및 각 속성 대응 유창하게 자기 장식 기능을 제공하는 문제를 통해 갈 필요가 없습니다.
나는 이것이 이제 오래된 질문이라는 것을 알고 있지만 이것에 대한 나의 생각을 당신과 나누고 싶었습니다.
할 수있을 때 일종의 메커니즘 인 유창함과 수업을 분리하는 것은 어떻습니까? 이것은 당신의 수업을 순수하게 만들 것입니다.
이런 건 어때?
수업
public class Person
{
public string FirstName { get; set; }
public string LastName {get; set;}
public override string ToString()
{
return $"First name: {FirstName} last name: {LastName}";
}
}
public class Customer : Person
{
public string AccountNumber { get; set; }
public long Id { get; set; }
public override string ToString()
{
return base.ToString() + $" account number: {AccountNumber} id: {Id}");
}
}
유창한 메커니즘을 추가하는 클래스
public class FluentCustomer
{
private Customer Customer { get; }
public FluentCustomer() : this(new Customer())
{
}
private FluentCustomer(Customer customer)
{
Customer = customer;
}
public FluentCustomer WithAccountNumber(string accountNumber)
{
Customer.AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(long id)
{
Customer.Id = id;
return this;
}
public FluentCustomer WithFirstName(string firstName)
{
Customer.FirstName = firstName;
return this;
}
public FluentCustomer WithLastName(string lastName)
{
Customer.LastName = lastName;
return this;
}
public static implicit operator Customer(FluentCustomer fc)
{
return fc.Customer;
}
public static implicit operator FluentCustomer(Customer customer)
{
return new FluentCustomer(customer);
}
}
Fluent 모드로 전환하는 확장 방법
public static class CustomerExtensions
{
public static FluentCustomer Fluent(this Customer customer)
{
return customer;
}
}
문제에서와 동일한 예
Customer customer = new Customer().Fluent()
.WithAccountNumber("000")
.WithFirstName("John")
.WithLastName("Smith")
.WithId(123);
참조 URL : https://stackoverflow.com/questions/2278781/fluent-interfaces-and-inheritance-in-c-sharp
'UFO ET IT' 카테고리의 다른 글
PHP 번호 : 필요한 경우에만 소수점 표시 (0) | 2020.12.31 |
---|---|
Database.EnsureCreated 및 Database.Migrate를 어디에서 어떻게 호출합니까? (0) | 2020.12.30 |
Drupal 행동 (0) | 2020.12.30 |
관리자로 실행중인 PowerShell에서 네트워크 드라이브에 액세스 할 수 없습니다. (0) | 2020.12.30 |
C에서 불투명 포인터는 무엇입니까? (0) | 2020.12.30 |