문제
C#에서 사이드 프로젝트로 네트워크 채팅 클라이언트를 만들고 있습니다. 간단한 문자 메시지 외에도 입력 텍스트 상자에 입력 할 수있는 슬래시 준비된 명령도 있습니다. 모든 다양한 명령이 포함 된 열거를 만들고 속성으로 해당 명령을 장식하여 모듈 식 접근법을 사용했습니다.
속성은 명령을 트리거하기 위해 Slash-Prefixed 명령을 입력 할 수있는 항목 및 기본 명령 식별자 및 명령의 사용법에 대한 별칭을 지정합니다.
예시:
public enum CommandType : byte
{
[PrimaryIdentifier("file"),
AdditionalIdentifier("f"),
CommandUsage("[<recipient>] [<filelocation>]")]
FileTransferInitiation,
[PrimaryIdentifier("accept"),
AdditionalIdentifier("a")]
AcceptFileTransfer,
// ...
}
여러 별칭을 기본 명령에 허용하려고 할 때 문제가 발생합니다. 나는이 두 가지 방법을 시도했다 : AdditionalIdentifier
속성, 또는 생성자 인수를 작성함으로써 AdditionalIdentifier
ㅏ params string[]
.
전자와 함께, 나는 속성 클래스를 AttributeUsage
그리고 설정 AllowMultiple
사실. 이것이 실제로 내가 찾고있는 것을 달성하지만, 다른 속성 외에도 여러 줄의 별명을 갖는 것이 실제로 시끄럽게 될 수 있다고 생각합니다.
후자는 또한 작동하지만 컴파일러 경고 CS3016, 그리고 그 접근법은 CLS를 준수하지 않는다고 말합니다. 분명히, 이것이 여전히 그것을 사용하는 것을 막을 수는 없지만, 나는 항상 경고를 오류로 취급하는 법을 배웠습니다.
내 실제 질문은 복제물로 이의 제기를 무시하고 계속 사용해야합니까, 아니면 사용할 수있는 다른 솔루션이 있습니까?
고맙습니다.
해결책
개인적으로 나는 허용 다중 접근 방식과 함께 갈 것입니다. 각 명령에 대한 트럭로드가 실제로 없다면 "소음"이 그다지 문제가 될 것이라고 생각하지 않습니다. 그러나 당신이 그것을 좋아하지 않고 CLS 호환을 유지하고 싶다면 다른 솔루션은 추가 식별자를 위해 과부하 된 생성자를 제공하는 것입니다.
public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }
단점은 이것이 미리 정해진 수의 식별자로 제한한다는 것입니다.
즉, CLS 규정 준수는 다른 사람들이 사용할 수있는 라이브러리 (특히 다른 언어에서)를 구축하는 경우 실제로 큰 고려 사항 일뿐입니다. 이 유형 또는 라이브러리가 응용 프로그램 내부 인 경우 CLS 준수 경고를 무시하는 것이 합리적입니다.
편집하다: 이것에 대해 더 생각하면, 당신은 그 열거에 대해 많은 속성을 가지고 있습니다. 대신 추상 명령 클래스를 만들고 식별자, 사용법 등을 해당 클래스의 속성으로 노출시키는 것을 고려할 수 있습니다. 그런 다음 해당 속성에서 적절한 값을 반환하는 구체적인 유형의 명령을 도출하십시오. 이를 통해 열거 값을 켜지 않고 처리 로직을 해당 명령 개체로 이동할 수 있습니다.
다른 팁
생성자에서 "params string [] aliases"를 사용하여 변수 인수 목록을 허용 할 수도 있습니다.
[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
public TestAttribute(params string[] aliases)
{
allowedAliases = aliases;
}
public string[] allowedAliases { get; set; }
}
이것은 당신이 할 수 있습니다 :
[Test("test1", "test2", "test3")]
static void Main(string[] args)
여러 속성을 가진 단일 속성이없는 이유는 무엇입니까? 별칭의 속성이 쉼표로 구분 된 목록을 가져 오도록하십시오. 이것은 역할에 대한 승인을 위해 MVC에서 취하는 접근법입니다. 내부적으로 속성은 속성을 속성 클래스에서 쉽게 사용할 수 있도록 배열로 문자열을 구문 분석하지만 구성을 쉽게 설정할 수 있습니다.
public class IdentifierAttribute
{
public string Name { get; set; }
public string Usage { get; set; }
private string[] aliasArray;
private string aliases;
public string Aliases
{
get { return this.aliases; }
set
{
this.aliases = value;
this.aliasArray = value.Split(',').Trim();
}
}
}
그런 다음 다음과 같이 사용하십시오.
public enum CommandType : byte
{
[Identifer( Name = "file", Aliases = "f", Usage = "..." )]
FileTransferType,
...
}
또 다른 접근법은 속성이 문자열 배열을 생성자 매개 변수로 취하는 것입니다. 그렇게하면 컴파일러가 배열을 구문 분석 할 수 있습니다 (속성을 적용 할 때 조금 더 goop을 희생하면).
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
이러한 기술을 구현하고 사용하는 빠른 'N Dirty 예제는 다음과 같습니다.
using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SomeClass.TellMeAboutYourself();
}
}
public class Identifiers : Attribute
{
private string[] names;
public Identifiers(string[] someNames)
{
names = someNames;
}
public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
}
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
static class SomeClass
{
public static void TellMeAboutYourself()
{
Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
foreach (var s in theAttribute.Names)
{
Console.WriteLine(s);
}
}
}
}