0

Mercurial 용 명령 줄 클라이언트를 래핑하는 클래스 라이브러리가 있습니다.확장 가능한 API를 만들고 개체 이니셜 라이저 구문을 사용하는 방법은 무엇입니까?

제 의도는 모든 내장 명령에 대한 지원을 구현하는 것입니다. 그러나 그 외에도 다양한 확장 기능이 있습니다.

그래서 다른 라이브러리와 확장 프로그램에 대한 지원을 추가 할 수 있다는 점에서 라이브러리를 확장 가능하게해야합니다. 좀 더 인기 있고 일반적인 확장 기능을 추가 할 계획이지만 (적어도 Mercurial과 함께 제공되는 확장 기능 중 상당수는 확장 기능을 제공 할 예정입니다.)하지만 여전히 외부에서 확장 할 수 있기를 원합니다. 순간

이 명령의 구문은 다음과 같이 :

Repo.Execute(new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}); 

이, 그러나, 확장이 단지가 압정으로 고정되는 느낌 프로그래머없이, 확장에 쉽게 적합하지 않습니다 부품. 예를 들어

, 그에게 내가 수동으로 할 수있는,의 내가 추가 명령 행 인수의 공개 수집을 노출 가정 해 봅시다 : 나 추가적인 확장을 추가 취득하는

var cmd = new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}; 
cmd.Arguments.Add("--my-commit-extension"); 
Repo.Execute(cmd); 

는 쉬운 방법을 없을 것 같다 객체 이니셜 라이저의 일부로 설정할 수 있습니다.

저는 유창한 인터페이스 구문을 추가하거나 변경하려고 생각했습니다. 이 경우 다음과 같이 쓸 수 있습니다.

Repo.Execute(new CommitCommand() 
    .Message("Your commit message") 
    .AddRemove() 
    .MyCommitExtension()); 

그러나 사람들은 유창한 인터페이스가 마음에 들지 않는다고 생각합니다. 사람들이 너무 수다스러운 것처럼 느낍니다.

다른 옵션에는 어떤 것이 있습니까?

는 기본적으로 내가 원하는 무엇 : 들어

  • 하나의 일반적인 구문 스타일
    • 모두 내장 내 라이브러리의 사용자가 추가 일
    • 뿐만 아니라 확장

필자는 내 라이브러리 사용자가 새로운 클래스를 추가하고 확장 메소드를 ge t 인텔리 센스 지원을 제공하지만 확장 메소드는 객체 초기화 프로그램에서 사용할 수 없습니다. 즉, 모든 확장은 나중에 고려해야합니다. 그건 내가 원하는 것이 아니야.

모든 아이디어를 환영합니다.

답변

1

저는 Mercurial에 익숙하지 않았기 때문에 귀하의 질문이 너무 구체적으로 다루어 지지만 특정 의견을 말씀 드릴 수는 있습니다.

var cmd = new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}; 
cmd.Arguments.Add("--my-commit-extension"); 
Repo.Execute(cmd); 

경우 CommitCommand.인수 IList<T> 당신은 이미 초기화 구문을 사용 할 수있는 기능이있다 :

class CommitCommand 
{ 
    public string Message { get; set; } 
    public bool AddRemove { get; set; } 
    public List<string> Arguments = new List<string>(); 
} 

Repo.Execute(new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
    Arguments = { "--my-commit-extension", "--my-other-commit-extension" } 
}); 
+0

네,하지만 :이 방식으로 명령을 사용할 수 있습니다

interface IExtension { ... } class SomeExtension1 : IExtension { ... } class SomeExtension2 : IExtension { ... } class CommitCommand { public string Message; public bool AddRemove; public readonly IList<IExtension> Extensions = new List<IExtension>(); } 

: 당신이 그것을 피하고 싶은 경우에, 나는 아마 다음과 같이 떨어지게을 사용 . 라이브러리 + 확장을 사용하는 프로그래머가 실제 인수를 알 필요가 없도록 일반적인 방법을 사용하려고합니다. –

+0

다이나믹을위한 좋은 사용법과 같은 소리입니다. – Tergiver

1

내가 너무 의욕과 그 익숙하지 않다,하지만 하나의 옵션은 익명 형식 IntelliSense를 버리고 사용하는 것입니다

Repo.Execute(new 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
    MyCommitExtension = null 
}); 

당신을 속성 이름에 하이픈을 사용할 수 없기 때문에 PascalCase에서 하이픈 - 소문자로 바꿔야합니다. 또는 밑줄을 하이픈으로 바꿀 수 있습니다.

은 사람들이 이러한 확장 프로그램을 사용할 빈도에 대해 잘 모른 채을 권장한다고 확신하지 않습니다. 이 접근법은 HTML 속성을 처리 할 때 ASP.NET MVC 프레임 워크에서 잘 작동하지만 프레임 워크가 값을 처리 할 필요가 없다는 점에서 다른 점이 있습니다. 단지 출력에 직접 씁니다. 이 방법으로 제공된 값을 기반으로 조건부 조치를 취하거나 Mercurial의 명령 행 구문을 모르는 사람들에게 API를 더 잘 보이게하려면 다른 접근 방식을 시도해보십시오.

0

유창한 인터페이스는 괜찮습니다. 죄송합니다, 내 실수, 나는 간단

new CommitCommand 
{ 
    Message = "", 
    AddRemove = true, 
    Extensions = {new SomeExtension1(), new SomeExtension2()} 
};